安全地在服务器上执行用户提交的Python代码
我正在考虑启动一个项目,这个项目需要执行用户通过HTML表单输入的Python代码。我知道这样做可能会很危险(因为使用了exec
),但我见过至少有一个例子成功实现了。
我给Python Challenge的开发者发了一封邮件,他们告诉我他们使用的是自己想出来的解决方案,只透露他们使用了“操作系统提供的安全功能”,并且“操作系统(Linux)提供了大部分你需要的安全性,只要你知道怎么使用它”。
有没有人知道安全可靠的方法来实现这个呢?我考虑过为每次提交启动一个新的虚拟机,但这样会消耗太多资源,而且几乎不可能高效地实现。
4 个回答
如果你以用户 nobody
的身份在 Linux 上运行这个脚本,它几乎无法写入任何地方,也无法读取那些权限设置得当的数据。但它仍然可能造成拒绝服务攻击,比如:
- 占满
/tmp
目录 - 消耗所有的内存
- 占用所有的 CPU 资源
此外,它还可以打开外部网络连接等等。你可能可以通过内核限制来锁定这些问题,但总会有一些东西你会忘记。
所以我认为,使用一个没有网络访问和真实硬盘的虚拟机是唯一(相对)安全的选择。也许 Python Challenge 的开发者使用的是 KVM,这在原则上是“由操作系统提供的”。
为了提高效率,你可以在同一个虚拟机中运行所有的提交。这可以节省很多开销,在最坏的情况下,它们只会互相影响,而不会影响到你的服务器。
http://codepad.org/about 成功地实现了这样一个系统(作为一个公共的代码粘贴和运行服务!)
codepad.org 是一个在线编译器/解释器,也是一个简单的协作工具。它就像一个可以执行代码的粘贴板。 [...]
它是如何工作的
代码的执行是由一个监督程序来处理的,这个程序基于 geordi。它的策略是通过一种叫做 ptrace 的方式来运行所有的代码,同时禁止或忽略很多系统调用。编译器和最终的可执行文件都在一个叫做 chroot 的沙箱里运行,并且有严格的资源限制。这个监督程序是用 Haskell 语言写的。
[...]
当你的应用涉及远程代码执行时,你必须考虑到安全问题。为了不单单依赖 chroot 和 ptrace 监督程序,我还采取了一些额外的安全措施:
监督程序运行在虚拟机上,这些虚拟机有防火墙,无法进行外部连接。
运行虚拟机的机器也有很强的防火墙,并且会定期从源镜像恢复。
在现代的Linux系统中,除了可以使用chroot(2)来限制进程外,还可以用clone(2)来代替fork(2)进一步限制进程。clone(2)有几个很有意思的选项:
CLONE_NEWIPC (new namespace for semaphores, shared memory, message queues)
CLONE_NEWNET (new network namespace - nice one)
CLONE_NEWNS (new set of mountpoints)
CLONE_NEWPID (new set of process identifiers)
CLONE_NEWUTS (new hostname, domainname, etc)
之前这个功能是在OpenVZ中实现的,后来被合并到了主流版本中,所以现在不需要再使用修改过的内核了。