执行不受信任的代码的最佳实践


31

我有一个项目,需要允许用户对我的服务器运行任意的,不受信任的python代码(有点像这样)。我是python的新手,我想避免犯任何会给系统带来安全漏洞或其他漏洞的错误。您是否可以提供最佳实践,推荐阅读或其他建议,以使我的服务可用但不可滥用?

到目前为止,这是我考虑过的内容:

  • __builtins__exec上下文中删除以禁止使用潜在危险的软件包,例如os。用户将只能使用我提供给他们的软件包。
  • 使用线程强制合理的超时。
  • 我想限制可以在exec上下文中分配的内存总量,但是我不确定是否可能。

有一些替代Straight的方法exec,但是我不确定其中哪些方法会有所帮助:

  • 使用ast.NodeVisitor捕获任何尝试访问不安全对象的尝试。但是我应该禁止哪些物品?
  • 搜索输入中的任何双下划线。(比上面的选项不太优雅)。
  • 使用PyPy或类似于沙箱的代码。

注意:我知道至少有一个基于JavaScript的解释器。在我的情况下,这行不通。



3
@MartijnPieters:非常好。如果您总结每个答案,可能都值得回答。
罗伯特·哈维

还请考虑:磁盘上剩余的垃圾,网络(不要让它们发送垃圾邮件等),对其他文件的权限(读取文件)。即使弹出while循环也会破坏CD的机制...我会选择虚拟化(监狱或您命名的某些kvm),或者至少是几乎没有特权的用户。设置合理的大小和内存量以利用自己的程序。
kyticka


1
尝试PyPy:>沙箱:PyPy提供了以完全安全的方式运行不受信任的代码的功能。
Vorac 2013年

Answers:


28

Python沙箱很难。Python本质上是自省的,具有多个层次。

这也意味着您可以从这些类型本身中找到特定类型的工厂方法,并构造新的低级对象,这些对象将由解释器直接运行而没有限制。

以下是一些寻找突破Python沙箱的创新方法的示例:

  • 内德•巴切德尔(Ned Batchelder)首先进行了演示,证明确实多么危险eval() ; eval()通常用于执行Python表达式;作为单行的原始和幼稚的沙箱。

    然后,他继续尝试将相同的原理应用于Python 3,最终成功地提出了一些有用的指针。

  • Pierre Bourdon使用类似的技术在hack-a-thon入侵python系统

基本思想始终是寻找一种创建基本Python类型的方法。函数和类,并通过使Python解释器执行任意(未经检查!)字节码来突破外壳。

exec语句(exec()Python 3中的函数)相同且更多。

因此,您想要:

  • 严格控制Python代码的字节编译,或者至少对字节代码进行后处理,以删除对所有以下划线开头的名称的访问。

    这需要对Python解释器如何工作以及Python字节码的结构有深入的了解。代码对象是嵌套的;模块的字节码仅覆盖语句的顶层,每个函数和类均包含自己的字节码序列以及元数据,例如,包含用于嵌套函数和类的其他字节码对象。

  • 您需要将可以使用的模块列入白名单。小心。

    python模块包含对其他模块的引用。如果您导入os,则os模块名称空间中有一个引用该os模块的本地名称。这可以将坚定的攻击者引导至可以帮助他们突破沙箱的模块。pickle例如,该模块可让您加载任意代码对象,因此,如果通过白名单模块的任何路径均通向该pickle模块,则仍然存在问题。

  • 您需要严格限制时间配额。即使是最绝望的代码仍然可以尝试永远运行,从而占用您的资源。

看一看RestrictedPython,它试图为您提供严格的字节码控制。RestrictedPython将Python代码转换为可以让您控制在Python 2.3至2.7中允许使用的名称,模块和对象的东西。

如果RestrictedPython是你的目的不依赖于你落实政策足够安全。不允许访问以下划线开头且严格将模块列入白名单的名称。

在我看来,唯一真正可靠的选择是使用单独的虚拟机,该虚拟机无法访问外部网络,而每次运行后都将其破坏。每个新脚本都会获得一个新的VM。这样,即使代码设法突破了您的Python沙箱(这也不是不可能),所有攻击者可以短期使用并且毫无价值。


10

TL; DR使用chroot / jail并以自定义用户身份运行,没有任何特权。

执行不受信任的代码的最佳实践是通过系统沙箱将其隔离。为了最安全:

  • 创建一个仅包含Python及其相关性和容器相关性的容器
  • 创建一个没有所有并非绝对必要的设备(例如,网络和存储)的容器
  • 创建一个对内存和进程使用有限制的容器
  • 每次运行(或至少每个唯一用户和最大时间段)重新创建容器
  • 以所需的最低特权作为用户运行
  • 以没有权限写入文件的用户身份运行

您还遵循标准惯例,以在chroot中安全地运行事物。您还可以在每次调用时重建chroot的文件系统,这尤其是偏执。通常,您只是使用户无法修改chroot运行所在的文件系统。


这是唯一要远程确保正确设置的事情-给它它自己的过程。
迈克尔·科恩

3

您无法安全地执行此操作。

如果您想安全地执行此类操作,则必须首先拥有自己的python实现,该实现在完全受控的环境中运行,最好在用户的浏览器而不是系统中运行。您可以从Jython(适用于Java的python)开始,并将其打包为Java applet。由于它将在用户计算机上的java沙箱中运行,因此您的系统将相当安全。


4
安全问题是服务器的问题,而不是客户的计算机的问题。与其他任何Web技术一样,Java的潜在安全隐患是该服务器可用于部署对客户端有害的程序。
2013年

1
@grasGendarme就像飞机失事的新故事一样,实际上告诉了您很多关于飞机失事的情况;有关Java安全漏洞的故事告诉您Java相对安全。您永远不会得到有关C的故事,因为您得到的响应将是“好吧;如果您运行它,它将做任何想要的事情”
Richard Tingle

2

正如Martijn前面所说,这在Python中确实非常困难。坦率地说,因为Python非常自省,我认为限制语言功能是不可能的。而且,如果您使用的沙箱适用于一个版本的Python,则下一个版本可能会破坏它。

我将看看PyPy而不是标准的CPython。简而言之,它是Python的兼容替代实现。它具有许多优点和独特功能,其中之一是通过替换系统调用而不是限制语言功能来进行沙箱处理。


0

只要性能对您不是很重要,就可以始终在Brython中运行它,从而将其有效地放入JavaScript沙箱中

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.