我正在编写一个应用程序,我希望用户能够为极端情况输入 python 文件。在我的脑海中,我能想到的最好方法是将他们的文件保存到磁盘并将位置保存到数据库,然后使用动态导入它__import__()
然后执行它。我的问题的第一部分是:这是最好的方法吗?
此外,这带来了一些相当大的安全问题。有没有办法在限制下运行他们的模块?不让它看到文件系统或任何东西?
编辑:
python 的执行将是从“正常”范围之外的后端服务中检索数据,因此它不会是一个完整的应用程序。它可能只是自定义协议的定义。
我正在编写一个应用程序,我希望用户能够为极端情况输入 python 文件。在我的脑海中,我能想到的最好方法是将他们的文件保存到磁盘并将位置保存到数据库,然后使用动态导入它__import__()
然后执行它。我的问题的第一部分是:这是最好的方法吗?
此外,这带来了一些相当大的安全问题。有没有办法在限制下运行他们的模块?不让它看到文件系统或任何东西?
编辑:
python 的执行将是从“正常”范围之外的后端服务中检索数据,因此它不会是一个完整的应用程序。它可能只是自定义协议的定义。
您可以使用compile
和内置的组合exec
在内存中执行。缺点是您不会在回溯中获得源代码行。
虽然对安全没有太大希望。即使您设置了可笑的限制性过滤器,例如将所有内容限制为单个表达式并删除大多数内置函数,也可以执行任意代码。在 Python 中禁止文件系统访问或对其他操作系统资源的访问也很困难,因为代码将在同一个进程中运行。有严格限制的子进程(chroot
监狱ulimit
等)是可能的,但这不仅需要大量工作,而且还排除了与主机应用程序交互的大多数方式。
如果您的应用程序在本地运行并且具有与用户帐户相同的权限,最好不要担心并给予他们更多的权力,因为他们不能做任何事情/无论如何他们不能做任何事情,并且大多数限制会使任务(无论是什么)更难/更烦人。另一方面,如果代码将在服务器或其他东西上执行,请忘记在同一进程中运行它。
您可以做几件事来限制权力(请参阅我对 OP 的评论)
但真的是我的两分钱......只需给每个用户自己的虚拟机(也许是 AWS?)......这样他们就不会搞砸了......你总是可以重新启动它......
更复杂的方法(但可以说更酷)是使用 lex/yacc(在 python 中它的 PLY)并定义您自己的语言(可能是 python 的有限子集)
您可以考虑以下方法
class _DynamicModule(object):
def __init__(self, name):
self._name = name
def load(self, code):
execdict = {'__builtins__': __builtins__}
exec compile(code, '<string>', 'exec') in execdict
for key in execdict:
if not key.startswith('_'):
if not isinstance(execdict[key], str):
execdict[key].__module__ = self._name
setattr(self, key, execdict[key])
return self
import sys
sys.modules['dummy_modules'] = _DynamicModule('dummy_modules').load('print ("!")')
这仍然有相当大的安全问题。