代码之家  ›  专栏  ›  技术社区  ›  Blixt

如何在纯python中沙盒python?

  •  47
  • Blixt  · 技术社区  · 14 年前

    我正在开发一个纯python的网络游戏,并希望提供一些简单的脚本来支持更动态的游戏内容。游戏内容可以由特权用户实时添加。

    如果脚本语言可以是Python,那就太好了。但是,由于恶意用户可能会造成严重破坏,因此它无法在访问游戏运行环境的情况下运行。是否可以在纯python中运行沙盒python?

    更新 :事实上,由于真正的Python支持会有点过火,使用python语法的简单脚本语言将是完美的。

    如果没有任何pythonic脚本解释器,是否还有其他用纯Python编写的开源脚本解释器可以使用?这些需求支持变量、基本条件和函数调用(而不是定义)。

    8 回复  |  直到 7 年前
        1
  •  42
  •   Aaron Digulla    11 年前

    这真的很重要。

    有两种方法可以沙盒python。一种是创造一个受限的环境(即很少的全球环境等),以及 exec 您在此环境中的代码。这就是梅萨的建议。这很好,但是有很多方法可以打破沙盒,制造麻烦。大约一年前,在python dev上有一个关于这个的线程,在这个线程中,人们做了一些事情,从捕获异常和戳入内部状态到爆发到字节代码操作。如果你想要一门完整的语言,这就是你要走的路。

    另一种方法是解析代码,然后使用 ast 将不需要的构造(例如导入语句、函数调用等)踢出的模块,然后编译其余的。如果您想将python用作配置语言等,这是一种可行的方法。

    另一种方法(因为你使用GAE,可能对你不起作用)是 PyPy sandbox . 虽然我自己还没用过,但有句话是说,这是唯一的 真实的 沙盒里的巨蟒。

    根据您对需求的描述(这些需求支持变量、基本条件和函数调用(而不是定义)),您可以 可以 想要评估方法2并从代码中剔除所有其他内容。这有点棘手,但可行。

        2
  •  6
  •   Messa    14 年前

    Afaik可以在完全隔离的环境中运行代码:

    exec somePythonCode in {'__builtins__': {}}, {}
    

    但在这样的环境中,你几乎什么也做不了:(你甚至不能 import 一个模块;但恶意用户仍然可以执行无限递归或导致内存不足。)您可能希望添加一些模块,作为游戏引擎的接口。

        3
  •  4
  •   Aaron Hall    7 年前

    我不知道为什么没有人提到这一点,但是Zope2有一个叫做python脚本的东西,也就是说,限制python在沙盒中执行,没有任何文件系统访问权,可以访问由Zope安全机制控制的其他Zope对象,导入限制在一个安全的子集内。

    总的来说,Zope是相当安全的,所以我想没有已知或明显的方法可以突破沙盒。

    我不确定Python脚本是如何实现的,但是这个特性和2000年一样。

    下面是蟒蛇脚本背后的魔力,以及详细的文档: http://pypi.python.org/pypi/RestrictedPython -它甚至看起来不依赖于Zope,因此可以独立使用。

    注意,这不是为了安全地运行任意的Python代码(大多数随机脚本在第一次导入或文件访问时都会失败),而是为了在Python应用程序中使用Python进行有限的脚本编写。

    这个答案是从我的评论到作为这个问题的复制品结束的一个问题: Python from Python: restricting functionality?

        4
  •  3
  •   Philip Tinney    14 年前

    我将研究双服务器方法。第一个服务器是代码所在的特权Web服务器。第二个服务器是一个严格控制的服务器,它只提供Web服务或RPC服务,并运行不受信任的代码。您为内容创建者提供了自定义界面。例如,如果您允许最终用户创建项目,您将看到一个调用服务器的查找,其中包含要执行的代码和参数集。

    这是治疗药水的抽象例子。

    {function_id='healing potion', action='use', target='self', inventory_id='1234'}
    

    答案可能是

    {hp='+5' action={destroy_inventory_item, inventory_id='1234'}}
    
        5
  •  2
  •   Will    14 年前

    嗯,这是一个思想实验,我不知道它是怎么做的:

    你可以用 compiler 包装到 parse 剧本。然后,您可以浏览这棵树,在所有标识符(变量、方法名e.t.c.)之前添加前缀。 has|get|setattr 调用等)-具有唯一的前导码,因此它们不可能引用变量。您还可以确保 编译程序 包本身没有被调用,可能还有其他黑名单的东西,比如打开文件。然后为此发出python代码,并且 compiler.compile 它。

    医生注意到 编译程序 包不在python 3.0中,但没有提到3.0的替代方案是什么。

    一般来说,这与Forum软件以及类似的将“safe”javascript或HTML e.t.c.列入白名单的做法是相似的,而且他们在历史上对所有逃犯的踩踏都有不良记录。但是你可能对巨蟒有更多的运气:)

        6
  •  2
  •   Ignacio Vazquez-Abrams    14 年前

    你可能会对 Python language services 用于编写自己的分析器的libref部分。

        7
  •  0
  •   Glenjamin    14 年前

    我认为你最好的选择是综合回答。

    您将希望解析输入并对其进行消毒—例如,删除任何导入语句。

    你可以用梅萨的 exec 示例(或类似的东西)只允许对您选择的内置变量执行代码-很可能是您自己定义的某种API,它提供程序员对您认为相关的功能的访问。

        8
  •  0
  •   coelhudo    7 年前

    你会发现一些想法 this wiki page 但看起来不容易做到。