这是场景:我的网站有一些不安全的代码,由网站用户生成,运行在我的服务器上。
我想禁用一些保留字对Python进行保护,例如eval,exec,print等等。
有没有一种简单的方法(不修改Python解释器,我的Python版本是2.7.10),可以实现我之前描述的功能?
非常感谢。
我想禁用一些保留字对Python进行保护,例如eval,exec,print等等。
有没有一种简单的方法(不修改Python解释器,我的Python版本是2.7.10),可以实现我之前描述的功能?
非常感谢。
禁用Python的名称在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')
此外,为了保护您的主机操作系统,请使用以下方法:
如果您选择使用 docker 进行容器化,则可能需要添加 AppArmor 或 SELinux 策略以提高安全性。 lxd 默认已经带有 AppArmor 策略。
请确保使用权限最低的用户运行代码。
对于每个用户,请重新构建虚拟机/容器。
无论您选择哪种解决方案,都不要忘记限制资源使用量(RAM、CPU、存储、网络)。如果您所选的虚拟化/容器化方案不支持此类限制,请使用 cgroups。
最后,使用超时来防止用户的代码永远运行。
def not_available(*args, **kwargs):
return 'Not allowed'
eval = not_available
exec = not_available
print = not_available
import builtins
builtins.print('this works!')
exec
不起作用,因为exec
是一个语句而不是函数,所以任何尝试分配给exec
都会引发SyntaxError:invalid syntax
。 而要使其适用于print
,您需要使用from __future__ import print_function
来禁用print
语句。 - PM 2Ring
eval
不是关键字,而是一个函数。eval = 8; print eval
。验证代码的最佳方法是将其解析为AST,然后扫描树以查找不安全的内容。但是...请参见此处。 - Amadaneval
的问题和建议。 - diaosihuaieval
,可以看看Stack Overflow老手Ned Batchelder的文章《Eval真的很危险》。该文章中有一些评论讨论使用ast
模块来清理用户提供的代码。 - PM 2Ring