可以将Python配置文件沙箱化吗?
我在考虑实现一个用Python语法写的配置文件,类似于Django的做法。
我看到过一些关于在配置文件中使用可执行代码的优缺点的讨论,但我想知道有没有办法在一个“沙箱”环境中执行这些配置文件的代码,这样可以避免代码中的错误导致主应用程序崩溃。
因为这个主应用程序是一个程序员的工具,所以我不担心教人Python语法或者引入安全漏洞的问题。不过,我确实担心配置代码可能会出现问题,导致主应用程序卡住。我更希望主应用程序能捕捉到这些问题,并显示出错误信息。
有没有人尝试过为Python配置文件做这种沙箱处理?如果有的话,哪些方法有效,哪些陷阱是我需要注意的?
2 个回答
很遗憾,使用标准的Python,你对这个问题能做的事情不多。当Python解释器在运行“配置代码”时,这段代码可以做任何事情,包括访问主程序或者不返回控制权。把配置代码放在一个单独的进程中运行可能会有所帮助,但这也会限制主程序和配置代码之间的互动。
你可以看看PyPy项目的沙箱功能。这可能正是你需要的,但也可能需要你花不少功夫来整合。
有没有替代rexec的Python沙箱方案?也讨论了这个话题。
你可能还需要问问自己,这个问题对你来说到底有多重要。我想这取决于你的使用场景,以及谁来编写配置代码。
我们这样做是为了我们的一些内部工具。
这样做可以保护我们免受异常问题的影响,并且不鼓励用户在配置脚本中进行过于创意的尝试。不过,这并不能防止无限循环或恶意第三方的攻击。
这个方法的核心是把脚本放在一个受限制的环境中执行。
首先,我们会查看 __ builtin __ 模块,删除所有我们不希望他们接触的东西,尤其是 __ import __。我们实际上是在一个上下文管理器中进行这个操作,它会在进入时备份原始值并删除它们,然后在退出时恢复原始值。
接下来,我们创建一个空字典,作为配置脚本的命名空间。
然后,我们在这个命名空间中执行配置脚本。
执行的过程当然是放在一个 try except 语句中,以捕捉任何可能出现的问题。
最后,我们检查命名空间,提取我们感兴趣的变量。
需要注意的几点:
虽然可能会想要在命名空间中预先填充一些对配置脚本有用的内容,但这样做要非常小心,因为这可能会让用户重新连接到主程序。
配置脚本仍然可以创建函数和类,所以你可能会得到一些看起来像字符串的东西,但实际上它可能是任意的可执行代码。
因此,我们规定配置脚本应该只产生纯粹的基本数据结构(通常是整数、字符串、列表、元组和 None),然后我们会单独验证这些数据。