Run an untrusted C program in a sandbox in Linux that prevents it from opening files, forking, etc.?

我想知道是否有一种方法可以在 Linux 的沙箱下运行一个不受信任的 C 程序。阻止程序打开文件、网络连接、分叉、执行等等的东西?

It would be a small program, a homework assignment, that gets uploaded to a server and has unit tests executed on it. So the program would be short lived.

51803 次浏览

我已经使用 Systrace在交互模式和自动模式下沙箱不受信任的程序。它有一个基于 ptrace()的后端,允许在没有特殊权限的 Linux 系统上使用,还有一个更快更强大的后端,需要对内核进行修补。

使用 chroot(1)在类 Unix 系统上创建沙箱也是可能的,尽管这并不那么容易或安全。Linux 容器FreeBSD 监狱是 chroot 的更好替代品。Linux 上的另一种选择是使用像 SELinux装甲这样的安全框架,这是我对生产系统的建议。

如果你告诉我们你到底想做什么,我们能帮你更多。

编辑:

Systrace 可能适合你的情况,但我认为基于 Linux 安全模型的东西,比如 AppArmar 或 SELinux,是一个更标准的,因此更受欢迎的选择,这取决于你的发行版。

编辑2:

虽然 chroot(1)可以在大多数(所有?)类 Unix 系统上使用,但它存在一些问题:

  • 它可以被打破。如果您打算在系统上实际编译或运行不受信任的 C 程序,那么您尤其容易受到这个问题的影响。如果你的学生和我的学生一样,就会有人试图越狱。

  • 您必须创建一个完全独立的文件系统层次结构,其中包含任务所需的所有内容。您不必在 chroot 中使用编译器,但是应该包含运行已编译程序所需的任何内容。虽然有一些实用程序可以帮助解决这个问题,但它仍然不是微不足道的。

  • 你必须保持根茎。因为它是独立的,所以 chroot 文件不会随您的发行版一起更新。您必须定期重新创建 chroot,或者在其中包含必要的更新工具,这基本上要求它是一个成熟的 Linux 发行版。您还必须保持系统和用户数据(密码、输入文件等)与主机系统同步。

  • chroot()只保护文件系统。它不能阻止恶意程序打开网络套接字或者一个写得很糟糕的程序占用所有可用的资源。

资源使用问题在所有替代方案中都很常见。文件系统配额将阻止程序填充磁盘。正确的 ulimit(C 中的 setrlimit())设置可以防止内存过度使用和任何叉子炸弹,以及停止对 CPU 的占用。nice(1)可以降低这些程序的优先级,使计算机可以用于任何被认为更重要的任务,没有问题。

在虚拟机中运行它应该可以提供您想要的所有安全性和限制。

QEMU would be a good fit for that and all the work (downloading the application, updating the disk image, starting QEMU, running the application inside it, and saving the output for later retrieval) could be scripted for automated tests runs.

试试 用户模式的 Linux。对于 CPU 密集型作业,它的性能开销约为1% ,但对于 I/O 密集型作业,它的性能开销可能要低6倍。

当它基于 ptrace (strace) check-out 进行散装时:

Sydbox”沙盒和“ 粉色痕迹”编程库(它是 C99,但据我所知,它们绑定到 python 和 Ruby)。

收集与主题相关的链接:

http://www.diigo.com/user/wierzowiecki/sydbox

(对不起,没有直接链接,但还没有足够的声望点)

I wrote an Linux 中的沙箱技术概述 recently. I think your easiest approach would be to use Linux containers (lxc) if you dont mind about forking and so on, which don't really matter in this environment. You can give the process a read only root file system, an isolated loopback network connection, and you can still kill it easily and set memory limits etc.

Seccomp is going to be a bit difficult, as the code cannot even allocate memory.

Selinux 是另一种选择,但我认为它可能比容器更费工夫。

您可以使用 Qemu 快速测试任务。下面的步骤在我5年前的笔记本电脑上只需不到5秒钟。

让我们假设学生必须开发一个接受无符号整型的程序,每个整型在自己的行上,直到到达一个带“-1”的行。然后程序应该对所有 int 进行平均,并输出“ Average:% f”。下面是完全隔离测试程序的方法:

  1. 首先,从 Jslinux 获取 root.bin,我们将使用它作为用户端(它有 tcc C 编译器) :

    wget https://github.com/levskaya/jslinux-deobfuscated/raw/master/root.bin

  2. 我们想把学生的提交放在 root.bin,所以设置循环设备:

    sudo losetup /dev/loop0 root.bin

    (也可以使用 fuseext2,但它不是很稳定。如果它稳定下来,你就不需要根了)

  3. 创建一个空目录:

    mkdir mountpoint

  4. 山脉 root.bin:

    sudo mount /dev/loop0 mountpoint

  5. 输入挂载的文件系统:

    cd mountpoint.

  6. 固定权利:

    sudo chown -R `whoami` .

  7. mkdir -p etc/init.d
  8. 返回文章页面

    #!/bin/sh
    cd /root
    echo READY 2>&1 > /dev/ttyS0
    tcc assignment.c 2>&1 > /dev/ttyS0
    ./a.out 2>&1 > /dev/ttyS0
    
  9. chmod +x etc/init.d/rcS

  10. Copy the submission to the VM:

    cp ~/student_assignment.c root/assignment.c

  11. Exit the VM's root FS:

    cd ..

  12. sudo umount mountpoint
  13. Now the image is ready, we just need to run it. It will compile and run the submission after booting.
  14. mkfifo /tmp/guest_output
  15. Open a seperate terminal and start listening for guest output:

    dd if=/tmp/guest_output bs=1

  16. In another terminal:

    qemu-system-i386 -kernel vmlinuz-3.5.0-27-generic -initrd root.bin -monitor stdio -nographic -serial pipe:/tmp/guestoutput (I just used the Ubuntu kernel here, but many kernels will work)

  17. When the guest output shows "READY", you can send keys to the VM from the qemu prompt. For example, to test this assignment, you could do

    (qemu) sendkey 1
    (qemu) sendkey 4
    (qemu) sendkey ret
    (qemu) sendkey 1
    (qemu) sendkey 0
    (qemu) sendkey ret
    (qemu) sendkey minus
    (qemu) sendkey 1
    (qemu) sendkey ret
    
  18. Now Average = 12.000000 should appear on the guest output pipe. If it doesn't, the student failed.

  19. Quit qemu: quit

A program passing the test is here: https://stackoverflow.com/a/14424295/309483. Just use tcclib.h instead of stdio.h.

好的,感谢所有的答案,他们帮了我很多。但我建议不要把它们作为提出原始问题的人的解决方案。所有提到的工具都需要做大量的工作来测试学生作为老师、导师、教授的代码,在我看来,这种情况下最好的方法是使用虚拟机。好吧,它模拟了一个完整的 x68系统,并没有任何意义的沙箱在这种方式,但如果我想象我的编程老师,这将是他最好的。因此,在 Debian 系统上的“ apt-get install viralbox”,所有其他用户都会访问 http://virtualbox.org/,创建一个 vm,添加一个 iso,单击 install,等待一段时间,然后就走运了。它将更容易使用,因为设置用户模式的 linux 或做一些重型 strace 的东西..。

如果你害怕你的学生攻击你,我猜你有一个权威问题和解决方案,那就是威胁他们,如果你能证明他们给你的工作中哪怕只有一点点男性软件,你就会起诉他们的黎明杀机... ..。

另外,如果有一个类,其中的1% 是他所能做到的最好的,不要让他们厌烦这些简单的任务,给他们一些大的任务,让他们编写更多的代码。综合性学习对每个人都是最好的,所以不要依赖于旧的僵局结构..。

当然,千万不要用同一台电脑来做重要的事情(比如写证明和考试) ,也不要用它来浏览网页和测试软件。

Use an off line computer for important things and an on line computer for all other things.

然而对于那些不是偏执狂的老师(不想冒犯任何人,我只是认为在你开始成为一名程序员老师之前,你应该学习一些关于安全和我们社会的基本知识...)

... 我在哪里... 对于其他人来说:

黑客快乐! !

seccomp and seccomp-bpf accomplish this with the least effort: https://www.kernel.org/doc/Documentation/prctl/seccomp_filter.txt

火监狱是最全面的工具之一,它支持 seccomp、文件系统容器、功能等等:

Https://firejail.wordpress.com/features-3/