动态读取python文件并安全地执行它

动态读取python文件并安全地执行它,python,Python,我正在编写一个应用程序,我希望用户能够输入角落案例的python文件。在我看来,我能想到的最好的方法是将他们的文件保存到磁盘,并将位置保存到数据库,然后使用\uuuuu import\uuuu()动态导入,然后执行它。我问题的第一部分是:这是最好的方法吗 此外,这也带来了一些相当大的安全问题。有没有办法在限制下运行他们的模块?不让它看到文件系统或任何东西 编辑: python的执行是从“正常”范围之外的后端服务检索数据,因此它不是完整的应用程序。它可能只是自定义协议的一个定义。 您可以考虑以下方

我正在编写一个应用程序,我希望用户能够输入角落案例的python文件。在我看来,我能想到的最好的方法是将他们的文件保存到磁盘,并将位置保存到数据库,然后使用
\uuuuu import\uuuu()
动态导入,然后执行它。我问题的第一部分是:这是最好的方法吗

此外,这也带来了一些相当大的安全问题。有没有办法在限制下运行他们的模块?不让它看到文件系统或任何东西

编辑:


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 ("!")')
class\u动态模块(对象):
定义初始化(self,name):
self.\u name=name
def加载(自身,代码):
execdict={'''uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
execdict中的exec编译(代码,,'exec')
对于execdict中的键:
如果不是键,则用(“”)启动:
如果不存在(execdict[key],str):
execdict[键]。\uuuuuu模块\uuuuuu=self.\u名称
setattr(self、key、execdict[key])
回归自我
导入系统
系统模块['dummy_modules']=\u动态模块('dummy_modules')。加载('print(!'))

这仍然有相当大的安全隐患。

您可以使用
编译
执行
内置代码的组合来在内存中执行。缺点是,在回溯中无法获得源代码行

不过,对安全问题没有多大希望。即使设置了限制性极强的过滤器,例如将所有内容限制在单个表达式中并删除大多数内置函数。在Python中禁止文件系统访问或访问其他操作系统资源也很困难,因为代码将在同一进程中运行。有严格限制的子进程(
chroot
jail,
ulimit
等)是可能的,但这不仅需要大量工作,而且还排除了与主机应用程序交互的大多数方式


如果您的应用程序在本地运行,并且具有与用户帐户相同的权限,那么最好不要担心,给他们更多的权限,因为他们不能做任何事情/做很多他们无论如何也做不到的事情,而且大多数限制会使任务(无论是什么)更难/更烦人。另一方面,如果代码将在服务器或其他地方执行,请忘记在同一进程中运行它。

您可以做一些事情来限制权限(请参阅我对OP的评论)

但实际上我的两分钱。。。只需给每个用户自己的虚拟机(可能是AWS?)。。。那样他们就不会搞砸了。。。你可以随时重新启动它


一种更复杂的方法(但可以说更酷)是使用lex/yacc(在python中)并定义自己的语言(可能是python的有限子集)

。。。我想把它作为一个答案。。。但实际上,只要阅读本文……我想我可以生成一个jvm的沙盒实例并在其中运行jython。这样,我就可以用python以外的语言编写用户代码。这有意义吗?我也遇到过,但我不确定这有多合法。@sir_charles804听起来是可行的。不过,我自己也会厌倦这样的事情,因为有很多机会搞砸。也就是说,我也会仔细检查做这件事的任何第三方项目(比如
pysandbox
),我同意。我想如果我这样做,它将与虚拟机。这样我就相信容器了。我还没有决定这是否是我让用户为角落案例指定连接的方式,但您的输入非常有用。谢谢