Python沙箱很难。Python本质上是自省的,具有多个层次。
这也意味着您可以从这些类型本身中找到特定类型的工厂方法,并构造新的低级对象,这些对象将由解释器直接运行而没有限制。
以下是一些寻找突破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沙箱(这也不是不可能),所有攻击者可以短期使用并且毫无价值。