运行不受信任的Python代码,使其能够与主程序通信但与系统隔离。

9
前言:我知道许多人已经尝试在Python中进行Python代码的沙盒化并失败了,但我没有看到过另外一种方法,即对脚本进行文本预处理并拒绝包含关键字(如__base__)的脚本,这些关键字可以用于恢复隐藏的__buuiltins__。我认为这种方法是新的,并且尚未被证明失败 - 是吗?
我计划编写一个多人策略游戏,在这个游戏中,玩家通常不能使用键盘/鼠标命令与他们的单位交互,而只能通过提交脚本来改变单位的自动行为。这基于以下想法:http://screeps.com
我很想用Python 3编写它,但主要问题似乎是在服务器上安全执行不受信任的外部玩家脚本。我知道我可能不信任exec()eval(),即使将空的globalslocals作为环境传递给它们。我也知道,仅仅擦除__builtins__也不起作用,因为可以使用Python的内省功能轻松地还原它们,如此处所述:http://nedbatchelder.com/blog/201302/finding_python_3_builtins.html 我已经了解到PyPy或Jython可能具有某种沙盒化功能,这可能适用于我的目的,但我更愿意使用CPython参考解释器。此外,我只能找到那些沙盒化功能适用于整个程序的示例,但没有一个由主程序运行不受信任的脚本作为子线程并与其高效通信的示例。
但我认为我还有一次机会:我可以对提交的脚本进行文本预处理,并搜索像__class____base__之类的字符串,并拒绝包含这些关键字的脚本。我还必须替换脚本中的eval()exec()为我的自己安全的函数,这些函数也拒绝运行包含这些关键字的代码。
这种方法是否与使用自定义globals参数覆盖所有潜在危险项(哪些是?)的exec()一起安全?我需要查找哪些关键字?
如果不是,为什么会失败?你能提出更好的解决方案吗?

你应该阅读这个其他的SO问题如何在纯Python中实现沙盒?(这似乎是一个重复的问题,但另一个问题现在已经相当老了...),也许还有Python沙盒,但它似乎只支持2.x版本。 - Serge Ballesta
@SergeBallesta 谢谢,问题很好,但是答案并不是我想要的。那些提到 exec 的方法不够安全,而那些提到其他解释器的方法也不完全符合我的要求。对于 PyPy 也是一样。 - Byte Commander
1个回答

1
我不确定这是否是一个好主意。使用pypy或者甚至是一个专门的项目python sandbox可能会有更多的可能性,因为它们已经处理了大部分系统隔离的问题。但前者需要大量工作来构建安全环境,后者则不直接支持Python 3.x。
但是,pysandbox的作者自2013年以来已停止开发,因为他在github网站上声明:
“pysandbox设计上存在问题,请转向新的沙盒解决方案(在沙盒中运行Python,而不是反过来!)https://lwn.net/Articles/574215/*”
如果您可以接受有限的语法,那么定义一个专用语法并使用PythonLexYacc构建自定义解释器肯定会更加安全。

我必须承认这只是一些提示而不是完整的答案,但现在这是我能做到的最好的(而且Python沙盒并没有被引用自那个之前的SO问题)。


pysandbox因存在漏洞,作者强烈反对使用:https://lwn.net/Articles/574215/ - Byte Commander
@ByteCommander:感谢您提供的参考。我会尝试在未来的答案中更新它,但这证实了我的第一个观点,即构建一个安全的Python解释器是对一个真正问题的错误解决方案 :-( - Serge Ballesta
但是如果我理解正确,他们只是使用Python方法来限制脚本进行隔离。我的方法是将原始脚本作为文本进行预处理,并简单地拒绝包含特殊关键字的所有脚本,例如__base__,这经常用于打破和重新创建__builtins__。这是一种不同的方法,不是吗?至少我还没有在网上找到相关信息。 - Byte Commander
@ByteCommander:我的理解是,如果您拒绝每个可能破坏安全沙箱的结构,那么您最终会得到一个无法用于比评估“1 +(2 * 3)”更复杂的内容的解释器。 - Serge Ballesta
不幸的是,我的游戏旨在让人们使用常规Python完全控制他们的单位...因此,PLY和过于严格都不是一个好选择... :( - Byte Commander

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接