如何在纯 Python 中实现 Python 沙盒化?

2024-12-30 08:41:00
admin
原创
43
摘要:问题描述:我正在用纯 Python 开发一款网页游戏,希望使用一些简单的脚本来实现更动态的游戏内容。特权用户可以实时添加游戏内容。如果脚本语言是 Python 就好了。但是,它无法在访问游戏运行环境的情况下运行,因为恶意用户可能会造成严重破坏,这很糟糕。是否可以在纯 Python 中运行沙盒 Python?更...

问题描述:

我正在用纯 Python 开发一款网页游戏,希望使用一些简单的脚本来实现更动态的游戏内容。特权用户可以实时添加游戏内容。

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

更新:事实上,由于真正的 Python 支持会有些过度,因此具有 Pythonic 语法的简单脚本语言将是完美的。

如果没有 Pythonic 脚本解释器,有没有其他用纯 Python 编写的开源脚本解释器可供我使用?要求支持变量、基本条件和函数调用(不是定义)。


解决方案 1:

这确实不是一件小事。

有两种方法可以对 Python 进行沙盒处理。一种是创建一个受限制的环境(即很少的全局变量等),并将exec代码放在这个环境中。这就是 Messa 所建议的。这很好,但是有很多方法可以打破沙盒并制造麻烦。大约一年前,Python-dev 上有一个关于这个问题的帖子,人们在其中做了一些事情,从捕获异常和探索内部状态到打破沙盒并进行字节码操作。如果您想要一种完整的语言,这就是要走的路。

另一种方法是解析代码,然后使用ast模块剔除不需要的构造(例如导入语句、函数调用等),然后编译其余部分。如果您想使用 Python 作为配置语言等,这就是要走的路。

另一种方法(由于您使用的是 GAE,因此可能不适合您)是PyPy 沙盒。虽然我自己没有用过它,但网上说它是唯一真正沙盒 Python。

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

解决方案 2:

在最初的问题提出大约十年后,Python 3.8.0 推出了审计功能。它能帮上忙吗?为了简单起见,我们将讨论限制在硬盘写入上 - 然后看看:

from sys import addaudithook
def block_mischief(event,arg):
    if 'WRITE_LOCK' in globals() and ((event=='open' and arg[1]!='r') 
            or event.split('.')[0] in ['subprocess', 'os', 'shutil', 'winreg']): raise IOError('file write forbidden')

addaudithook(block_mischief)

到目前为止exec可以轻松写入磁盘:

exec("open('/tmp/FILE','w').write('pwned by l33t h4xx0rz')", dict(locals()))

但我们可以随意禁止它,这样就没有恶意用户可以通过提供给 的代码访问磁盘exec()。Pythonic 模块喜欢numpypickle最终使用 Python 的文件访问,因此它们也被禁止写入磁盘。外部程序调用也已被明确禁用。

WRITE_LOCK = True
exec("open('/tmp/FILE','w').write('pwned by l33t h4xx0rz')", dict(locals()))
exec("open('/tmp/FILE','a').write('pwned by l33t h4xx0rz')", dict(locals()))
exec("numpy.savetxt('/tmp/FILE', numpy.eye(3))", dict(locals()))
exec("import subprocess; subprocess.call('echo PWNED >> /tmp/FILE', shell=True)",     dict(locals()))

尝试从内部移除锁exec()似乎是徒劳的,因为审计钩子使用了 的不同副本,locals而 运行的代码无法访问该副本exec。请证明我错了。

exec("print('muhehehe'); del WRITE_LOCK; open('/tmp/FILE','w')", dict(locals()))
...
OSError: file write forbidden

当然,顶层代码可以再次启用文件 I/O。

del WRITE_LOCK
exec("open('/tmp/FILE','w')", dict(locals()))

事实证明,在 Cpython 中使用沙盒非常困难,之前的许多尝试都失败了。这种方法也不完全安全,例如对于公共 Web 访问:

  1. 也许使用直接 OS 调用的假设编译模块无法通过 Cpython 审核——建议将安全的纯 Pythonic 模块列入白名单。

  2. 当然,Cpython 解释器仍然存在崩溃或过载的可能性。

  3. 也许还存在一些漏洞可以将文件写入硬盘。但我无法使用任何常见的沙盒规避技巧来写入单个字节。我们可以说 Python 生态系统的“攻击面”减少到相当狭窄的允许(禁止)事件列表: https: //docs.python.org/3/library/audit_events.html

如果有人能向我指出这种方法的缺陷,我将不胜感激。


编辑:所以这也不安全!我非常感谢@Emu使用异常捕获和自省的巧妙破解:

#!/usr/bin/python3.8
from sys import addaudithook
def block_mischief(event,arg):
    if 'WRITE_LOCK' in globals() and ((event=='open' and arg[1]!='r') or event.split('.')[0] in ['subprocess', 'os', 'shutil', 'winreg']):
        raise IOError('file write forbidden')

addaudithook(block_mischief)
WRITE_LOCK = True
exec("""
import sys
def r(a, b):
    try:
        raise Exception()
    except:
        del sys.exc_info()[2].tb_frame.f_back.f_globals['WRITE_LOCK']
import sys
w = type('evil',(object,),{'__ne__':r})()
sys.audit('open', None, w)
open('/tmp/FILE','w').write('pwned by l33t h4xx0rz')""", dict(locals()))

我认为审计+子处理是可行的方法,但不要在生产机器上使用它:

https://bitbucket.org/fdominec/experimental_sandbox_in_cpython38/src/master/sandbox_experiment.py

解决方案 3:

我不知道为什么没有人提到这一点,但是 Zope 2 有一个叫做 Python 脚本的东西,它就是这样 - 在沙箱中执行的受限 Python,无法访问文件系统,但可以访问由 Zope 安全机制控制的其他 Zope 对象,并且导入仅限于安全子集。

Zope 总体来说是相当安全的,因此我认为没有已知或明显的方法可以突破沙箱。

我不确定 Python 脚本是如何实现的,但该功能自 2000 年就已经存在了。

这里是 PythonScripts 背后的魔力,并附有详细的文档:http://pypi.python.org/pypi/RestrictedPython - 它甚至看起来不依赖 Zope,因此可以独立使用。

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

这个答案来自我对一个问题的评论,该问题已被关闭,因为它是这个问题的重复:Python 中的 Python:限制功能?

解决方案 4:

更新:此技术不会阻止创建自定义代码对象。请参阅评论。


据我所知,可以在完全隔离的环境中运行代码:

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

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

解决方案 5:

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

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

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

响应可能类似于

{hp='+5' action={destroy_inventory_item, inventory_id='1234'}}

解决方案 6:

您可以简单地禁止“dunder”访问并限制内置函数和其他全局函数:

if "__" not in code:
  eval(code, {'__builtins__': {}}, {});

所有规避沙箱的机制都需要 dunder 访问权限。此时,您可以小心地重新添加您希望用户有权访问的全局变量(甚至允许的导入)。

例如:

if "__" not in code:
  eval(code, {'__builtins__': {'__import__': my_safe_importer}}, {});

净化 + 限制应该足够了。我读过很多关于逃避沙箱的博客和文章,100% 的技术都使用了 dunder 访问。

另外,此模块采用更细致和经过测试的方法为您完成艰苦的工作(防止 dunder 访问):

https://restrictedpython.readthedocs.io/en/latest/

维护得很好:

from RestrictedPython import compile_restricted

source_code = "1+1"

byte_code = compile_restricted(
    source_code,
    filename='<inline code>',
    mode='eval'
)
eval(byte_code, {'__builtins__': {}}, {})

解决方案 7:

嗯。这是一个思想实验,我不知道有人做过:

您可以将compiler包用于parse脚本。然后,您可以遍历这棵树,为所有标识符(变量、方法名称等(还有has|get|setattr调用等))添加唯一的前缀,以便它们不可能引用您的变量。您还可以确保包compiler本身没有被调用,也许还有其他列入黑名单的东西,例如打开文件。然后,您为此发出 python 代码,然后compiler.compile它。

文档指出该compiler包不在 Python 3.0 中,但没有提到 3.0 的替代品是什么。

总的来说,这与论坛软件等尝试将“安全”的 Javascript 或 HTML 等列入白名单的方式类似,而且它们在阻止所有逃逸方面有着不良记录。但使用 Python 可能会更幸运 :)

解决方案 8:

我认为最好的选择是综合迄今为止的所有答复。

您需要解析并清理输入 - 例如删除所有导入语句。

然后,您可以使用 Messa 的exec示例(或类似内容)来允许仅针对您选择的内置变量执行代码 - 很可能是您自己定义的某种 API,可为程序员提供对您认为相关的功能的访问权限。

相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   997  
  在项目管理领域,CDCP(Certified Data Center Professional)认证评审是一个至关重要的环节,它不仅验证了项目团队的专业能力,还直接关系到项目的成功与否。在这一评审过程中,沟通技巧的运用至关重要。有效的沟通不仅能够确保信息的准确传递,还能增强团队协作,提升评审效率。本文将深入探讨CDCP...
华为IPD流程   34  
  IPD(Integrated Product Development,集成产品开发)是一种以客户需求为核心、跨部门协同的产品开发模式,旨在通过高效的资源整合和流程优化,提升产品开发的成功率和市场竞争力。在IPD培训课程中,掌握关键成功因素是确保团队能够有效实施这一模式的核心。以下将从五个关键成功因素展开讨论,帮助企业和...
IPD项目流程图   40  
  华为IPD(Integrated Product Development,集成产品开发)流程是华为公司在其全球化进程中逐步构建和完善的一套高效产品开发管理体系。这一流程不仅帮助华为在技术创新和产品交付上实现了质的飞跃,还为其在全球市场中赢得了显著的竞争优势。IPD的核心在于通过跨部门协作、阶段性评审和市场需求驱动,确保...
华为IPD   39  
  华为作为全球领先的通信技术解决方案提供商,其成功的背后离不开一套成熟的管理体系——集成产品开发(IPD)。IPD不仅是一种产品开发流程,更是一种系统化的管理思想,它通过跨职能团队的协作、阶段评审机制和市场需求驱动的开发模式,帮助华为在全球市场中脱颖而出。从最初的国内市场到如今的全球化布局,华为的IPD体系在多个领域展现...
IPD管理流程   71  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用