我正在开发一个基于django的web应用程序,它以python文件作为输入,其中包含一些函数,然后在后端我有一些列表,这些列表作为参数通过用户函数传递,这将生成一个单值输出。生成的结果将用于进一步的计算
以下是用户文件中的函数的外观:
def somefunctionname(list):
''' some computation performed on list'''
return float value
目前我使用的方法是将用户的文件作为正常的文件输入。然后在my views.py中,我将文件作为模块执行,并使用eval函数传递参数。下面给出了这个片段
这里modulename是我从user获取的python文件名,并作为模块导入
exec("import "+modulename)
result = eval(f"{modulename}.{somefunctionname}(arguments)")
这是绝对好的。但我知道这不是安全的方法
我的问题是,当我使用的方法不安全时,是否有其他方法可以安全地运行用户文件?我知道提议的解决方案不能完全证明,但我可以用什么其他方式来运行它(比如,如果可以通过dockerization来解决,那么我可以用什么方法或一些外部工具来使用API)? 或者,如果可能的话,有人能告诉我如何简单地沙箱这个或任何教程,可以帮助我
任何参考资料或资源都会有所帮助
这是一个重要的问题。在python中,沙箱并不是一件小事
这是为数不多的几个问题之一,其中一个问题是您正在使用哪个版本的python解释器。例如,Jyton生成Java字节码,JVM有自己的机制来安全地运行代码
对于默认解释器CPython,最初有一些尝试创建restricted execution mode,但很久以前就被放弃了
目前,有一个非官方的项目,RestrictedPython可能会给你你需要的东西。它不是一个完整的沙箱,也就是说,它不会给您提供受限的文件系统访问或其他功能,但对于您的需要,它可能就足够了
基本上,那里的人只是以一种更严格的方式重写了python编译
它允许做的是编译一段代码,然后在受限模式下执行。例如:
使用内置程序运行=safe\u内置程序会禁用危险的功能,如打开文件、导入或其他功能。还有其他的内置版本和其他选项,需要一些时间阅读文档,它们非常好
编辑:
下面是一个用例示例
现在有了一个函数
execute_user_code
,它以字符串形式接收一些不安全的代码、来自该代码的函数名、参数,并返回带有给定参数的函数的返回值下面是一些用户代码的一个非常愚蠢的示例:
但当用户代码试图做一些不安全的事情时,会发生以下情况:
可能的扩展名:
请注意,每次调用函数时都会编译用户代码。但是,您可能希望编译一次用户代码,然后使用不同的参数执行它。因此,您所要做的就是将
byte_code
保存到某个地方,然后每次使用不同的restricted_locals
集调用execEDIT2:
如果您想使用导入,您可以编写自己的导入函数,只允许使用您认为安全的模块。例如:
注意,这个示例导入函数非常原始,它不能处理
from x import y
之类的东西。您可以在here中查找更复杂的实现EDIT3
请注意,许多python内置功能在RestrictedPython中不可用,这并不意味着它根本不可用。您可能需要实现一些功能才能使其可用
即使是一些明显的东西,如
sum
或+=
操作符,在受限环境中也不明显例如,
for
循环使用_getiter_
函数,您必须自己实现并提供(在全局中)。由于您希望避免无限循环,因此可能需要对允许的迭代次数进行一些限制。下面是一个将迭代次数限制为100次的示例实现:如果不想限制循环计数,只需使用identity函数作为
_getiter_
:请注意,仅限制循环计数并不能保证安全性。首先,循环可以嵌套。其次,不能限制
while
循环的执行计数。为了保证安全,您必须在某个超时下执行不安全的代码请花点时间阅读docs
请注意,并非所有内容都有文档记录(尽管许多内容都有文档记录)。你必须学会阅读项目的source code以了解更高级的东西。最好的学习方法是尝试并运行一些代码,看看缺少什么样的函数,然后查看项目的源代码以了解如何实现它
EDIT4
还有一个问题-受限代码可能有无限循环。为了避免这种情况,代码需要某种超时
不幸的是,由于您使用的是django,除非您明确指定,否则这是多线程的否则,使用signeals进行超时的简单技巧在这里将不起作用,您必须使用多处理
在我看来,最简单的方法就是使用this library。只需向
execute_user_code
添加一个装饰器,它将如下所示:你就完了。代码的运行时间不会超过5秒。 注意使用_signals=False,否则在django中可能会出现一些意外行为
还要注意的是,这对资源来说是相对沉重的(我真的看不到克服这一点的方法)。我的意思是不是真的疯狂重,但它是一个额外的过程产卵。您应该记住,在web服务器配置中,允许执行任意用户代码的api更容易受到ddos攻击
当然,如果你小心的话,你可以用docker来沙箱执行。您可以限制CPU周期、最大内存、关闭所有网络端口、以对文件系统具有只读访问权限的用户身份运行(等等)
尽管如此,我认为这将是非常复杂的事情。对我来说,你不应该允许客户执行这样的套利代码
我会检查生产/解决方案是否已经完成并使用它。我认为有些站点允许您提交一些在服务器上执行的代码(python、java等等)
相关问题 更多 >
编程相关推荐