我正在尝试构建一个 Web 应用程序(在 Linux 服务器上运行),其中用户将上传一个可执行文件,该可执行文件将根据服务器上可用的特定输入(通过 STDIN 提供)运行,并且输出(从 STDOUT 读取)将返回给用户。
当然,我不希望用户能够在我的服务器上做任何恶意的事情。我想在沙箱,或者以其他方式阻止可执行文件执行敏感的系统调用。
我不知道该从哪里开始。我查看了用户模式Linux,但它似乎有太多的开销(许多可执行文件将并行运行,并且每个可执行文件都有一个虚拟机的开销太大了)。
我该如何继续?
编辑:我知道这是人们通常会避免的事情。我知道这样做有风险。请考虑一下,为了学习如何做到这一点,你会这样做。我以前在以下地方见过这种情况:密码键盘和乔迪,有时候这是非常方便的一件事。
答案1
你正在服用大量大量的运行不受信任的代码的风险。如果我想到的问题的答案是“在我的服务器上运行来自任意用户的不受信任的代码”,我会彻底重新考虑我想要做的事情以及项目的基本假设。
答案2
您可以尝试自由限制。
它是一个小型库,设计用于在启动给定的可执行文件之前进行 LD_PRELOAD,基本上通过 chroot() 进入给定目录,然后删除所有功能(基于白名单的功能除外),然后 setuid() 为给定用户,防止给定的可执行文件做恶意的事情。
这个程序的优点之一是它在系统加载了所有必要的库之后才会 chroot(),因此如果您很幸运(它不想 dl() 其他一些库)您可以将它与一个空目录一起使用,作为 chroot() 环境。
虽然它有点老旧并且没有文档,但你可以尝试一下,我可以帮助你。
答案3
我认为在虚拟机中运行可执行文件是您最好的选择。例如,#bash IRC 频道上有一个机器人,允许执行任意 shell 代码...通过在基于 qemu 的 VM 中运行它,然后捕获该进程的标准输出。UML 可能是一个相当好的解决方案。
新客人的东西(http://lguest.ozlabs.org/) 可能更好;这是“容器”机制,而不是全面的“虚拟化”解决方案;类似于 Solaris Zones。我不知道这个项目现在的状态如何。
答案4
我尝试了类似的东西,并选择了启用 grsecurity 的内核加上只读绑定挂载,以便在主机和沙箱之间共享系统文件。然后在 chroot 沙箱中启动测试应用程序。完成后,所有属于沙箱用户的进程都会被 SIGKILL 杀死,任何用户可修改的文件都会从原始文件中被删除和替换。虽然它可能不像虚拟机那样完全安全,但如果做得正确,它就非常接近了。优点是开销要小得多。