如何安全地运行不受信任的 python 代码?

dia*_*uai 7 python sandbox

这是这样的场景,我的网站有一些由网站用户生成的不安全代码,可以在我的服务器上运行。

我想禁用 python 的一些保留字以保护我的运行环境,例如evalexecprint

有没有一种简单的方法(不改变python解释器,我的python版本是2.7.10)来实现我之前描述的功能?

Kri*_*ris 5

在 python 级别禁用名称不会有帮助,因为有很多方法可以解决它。有关更多信息,请参阅文章和此帖子。这是你需要做的:

对于 CPython,使用RestrictedPython定义 Python 的受限子集。

对于 PyPy,请使用沙箱。它允许您在序列化所有输入/输出的特殊环境中运行任意 python 代码,以便您可以在实际运行它们之前检查并决定允许哪些命令。

自 3.8 版本起,Python 支持审计挂钩,因此您可以完全阻止某些操作:

import sys

def audit(event, args):
    if event == 'compile':
        sys.exit('nice try!')

sys.addaudithook(audit)

eval('5')
Run Code Online (Sandbox Code Playgroud)

此外,为了保护您的主机操作系统,请使用

  • 虚拟化(更安全),例如 KVM 或 VirtualBox

  • 或容器化(更轻),例如lxddocker

在使用 docker 进行容器化的情况下,您可能需要添加 AppArmor 或 SELinux 策略以提高安全性。默认情况下,lxd 已附带 AppArmor 策略。

确保您以具有尽可能少权限的用户身份运行代码。

为每个用户重建虚拟机/容器。

无论您使用哪种解决方案,都不要忘记限制资源使用(RAM、CPU、存储、网络)。如果您选择的虚拟化/容器化解决方案不支持此类限制,请使用cgroup 。

最后但并非最不重要的一点是,使用超时来防止用户的代码永远运行。


Bur*_*lid 0

一种方法是隐藏方法:

def not_available(*args, **kwargs):
    return 'Not allowed'

eval = not_available
exec = not_available
print = not_available
Run Code Online (Sandbox Code Playgroud)

然而,聪明的人总是可以做到这一点:

import builtins
builtins.print('this works!')
Run Code Online (Sandbox Code Playgroud)

因此,真正的解决方案是解析代码,如果有此类语句则不允许输入(而不是尝试禁用它们)。