在Linux的沙箱中运行不受信任的C程序,以防止其打开文件,派生等。


110

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

这将是一个小程序,是一项家庭作业,它被上传到服务器并在其上执行了单元测试。因此该程序将是短暂的。


这就像是一个C语言程序,您需要运行1次5分钟,还是需要不断运行?
bwawok

这将是一个上传并具有单元测试的小型程序。因此该程序将是短暂的。
Frank

系统使用什么发行版?一些发行版具有用于沙箱的现成工具。您的系统是否启用了任何安全模型,例如SELinux或AppArmor?
thkala 2010年

我正在使用Fedora13。我正在研究SELinux沙箱策略。我想知道还有哪些其他选择。
Frank

Answers:


47

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

也可以使用chroot(1),在类似Unix的系统上创建沙箱,尽管这并不那么容易或安全。Linux容器FreeBSD监狱是chroot的更好选择。Linux上的另一种选择是使用安全框架,例如SELinuxAppArmor,这是我对生产系统提出的建议。

如果您告诉您您想做什么,我们将能够为您提供更多帮助。

编辑:

Systrace可以满足您的情况,但是我认为基于Linux安全模型(例如AppArmor或SELinux)的东西是更标准的,因此根据您的分布情况,它是首选的替代方法。

编辑2:

虽然chroot(1)在大多数(所有?)类Unix系统上都可用,但是它有很多问题:

  • 它可以被打破。如果要在系统上实际编译或运行不受信任的C程序,则特别容易受到此问题的影响。而且,如果您的学生像我的一样,那么有人将试图越狱。

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

  • 您必须维护chroot。由于它是独立的,因此chroot文件不会随您的发行版一起更新。您将必须定期重新创建chroot,或在其中包含必要的更新工具,这实际上要求它是成熟的Linux发行版。您还必须使系统和用户数据(密码,输入文件等)与主机系统保持同步。

  • chroot()仅保护文件系统。它不能防止恶意程序打开网络套接字,也不能阻止编写错误的程序占用所有可用资源。

资源使用问题在所有替代方案中都很常见。文件系统配额将阻止程序填充磁盘。适当的ulimitsetrlimit()C语言)设置可以防止内存过度使用和任何fork炸弹,并制止CPU消耗。nice(1)可以降低这些程序的优先级,以便计算机可以毫无问题地用于被认为更重要的任何任务。


systrace对我来说适用于简单的程序,但是当GCC as(1)由GCC运行时,它无限地卡住了。所以我放弃了。这是systrace中的一个未修复的错误:forum.soft32.com/linux/…–
pts

有没有一种方法可以确保沙盒进程之间不共享共享内存,消息队列和信号量?
daveagp 2014年

1
systrace链接已损坏。
Collin

2
那Firejail呢?您不必再使用它来维护fs。
m3nda '16

18

我最近写了Linux中沙箱技术概述。我认为,如果您不介意派生等等,最简单的方法就是使用Linux容器(lxc),在这种环境下这并不重要。您可以为该进程提供一个只读的根文件系统,一个隔离的回送网络连接,并且仍然可以轻松地将其杀死并设置内存限制等。

由于代码甚至无法分配内存,因此Seccomp会有些困难。

Selinux是另一种选择,但我认为它可能比容器还要工作。


6

您可以使用Qemu快速测试任务。在我5岁的笔记本电脑上,下面的过程不到5秒。

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

  1. 首先,root.bin从Jslinux 获得,我们将其用作用户区(它具有tcc C编译器):

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

  2. 我们要将学生的提交内容放在中root.bin,因此设置循环设备:

    sudo losetup /dev/loop0 root.bin

    (您也可以为此使用fuseext2,但它不是很稳定。如果稳定,则不需要root用户)

  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. vi etc/init.d

    #!/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. 将提交内容复制到VM:

    cp ~/student_assignment.c root/assignment.c

  11. 退出VM的根FS:

    cd ..

  12. sudo umount mountpoint
  13. 现在映像已准备就绪,我们只需要运行它即可。它将在启动后编译并运行提交。
  14. mkfifo /tmp/guest_output
  15. 打开一个单独的终端并开始监听来宾输出:

    dd if=/tmp/guest_output bs=1

  16. 在另一个终端:

    qemu-system-i386 -kernel vmlinuz-3.5.0-27-generic -initrd root.bin -monitor stdio -nographic -serial pipe:/tmp/guestoutput (我在这里仅使用了Ubuntu内核,但是许多内核都可以使用)

  17. 当访客输出显示“ READY”时,可以从qemu提示符向VM发送密钥。例如,要测试此分配,您可以

    (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. 现在Average = 12.000000应该显示在来宾输出管道上。如果不是,则学生失败。

  19. 退出qemu: quit

通过测试的程序在这里:https : //stackoverflow.com/a/14424295/309483。只需使用tcclib.h代替即可stdio.h


5

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


4

Firejail是执行此操作的最全面的工具之一-它支持seccomp,文件系统容器,功能以及更多功能:

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


考虑到firejail可以通过大量文档进行积极维护,这个答案非常好,它确实值得更多推荐,它涵盖了大多数(如果不是全部)其他答案,并且设计成相对易于使用。
杰夫·海金

3

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

QEMU非常适合此操作,所有工作(下载应用程序,更新磁盘映像,启动QEMU,在其中运行应用程序以及保存输出以供以后检索)都可以编写脚本以进行自动化测试。


2
我不了解OP,但是在许多情况下,按测试程序启动VM是不可接受的。在我的环境(我是助教)中,最多有200名学生在2个小时内提交10-12个课程。没有任何程序可以运行超过10秒的CPU时间,但是当提交的文件堆积时,我们得到的周转时间为15分钟或更长时间。为每个程序引入VM会使每个程序的CPU时间延长到60秒或更多,我根本不想考虑周转时间。也许每个会话都有一个VM,但是我们无法按程序执行该操作……
thkala 2010年

@thkala这是一个好点。我喜欢QEMU的想法,但是为每个提交启动VM都是不好的。
Frank

好吧,在这种情况下,请始终保持同一台VM运行。
Laurent Parenteau

您是否可以使用已全部引导并准备编译和运行代码的vm快照来执行某些操作?仅供参考,虚拟机不一定不受穿孔的影响。您还可以构建一个硬件版本-一个小型系统,该系统可以从只读媒体或通过网络启动恢复映像,并通过网络或串行提供输出,然后为下一个重新启动。已经有一些快速启动的进展,可以使Linux在几秒钟内启动。
克里斯·斯特拉顿

@thkala:如果您连续运行它们,则每次提交所需的时间少于3秒。我发布的方法在现代计算机上大概需要3秒钟(串行)。如果并行化(也可以并行化),它将足够快。
Janus Troelsen


3

seccomp和seccomp-bpf可以毫不费力地完成此任务:https ://www.kernel.org/doc/Documentation/prctl/seccomp_filter.txt




-1

好的,感谢所有答案,他们对我有很大帮助。但对于那些提出原始问题的人,我不建议使用它们作为解决方案。为了测试学生作为老师,老师,教授的代码,所有提到的工具都需要大量的工作。我认为这种情况下最好的方法是virtualbox。好的,它模拟了一个完整的x68系统,并且与这种方式的沙盒无关,但是如果我想象我的编程老师,那对他来说将是最好的。因此,在基于debian的系统上进行“ apt-get install virtualbox”安装,其他所有工具都可以访问http://virtualbox.org/。,创建一个vm,添加一个iso,单击install,稍等片刻,幸运的是。设置用户模式linux或进行一些繁琐的strace操作将更加容易...

而且,如果您担心学生会被黑客入侵,我想您可能有一个权限问题,而如果您能证明他们所做的工作中只有一小撮恶意软件,那么您将起诉他们,要求他们起诉生活中的日光灯。您...

同样,如果有一门课,并且其中的1%就是他能做的那样好,那就不要让他们承受如此简单的任务,而给他们一些大的任务,而他们不得不编写更多的代码。集成式学习对每个人都是最好的,所以不要依赖旧的死锁结构。

因此,绝对不要将用于浏览网络和测试软件等重要内容的同一台计算机(例如编写证明和考试)。

对于重要的事情,请使用脱机计算机,对于所有其他事情,请使用联机计算机。

但是对于不是偏执狂老师的其他所有人(不想冒犯任何人,我只是认为,在您开始成为程序员老师之前,您应该学习有关安全性和我们社会的基础知识...)

...我在哪里...其他所有人:

快乐黑客!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.