如何安全地使用exec?我想使用动态加载的代码模块作为配置文件

时间:2013-11-01 04:55:09

标签: python module exec configuration-files

Software Carpentry上阅读Handling Configuration Files文章后,我对他们的方法#5感兴趣:将参数放入动态加载的代码模块中。基本上我希望能够在输入文件中进行计算以创建变量。

基于how to import a string as a module的SO答案,我编写了以下函数来导入字符串或文件对象或STringIO作为模块。然后我可以使用。访问varibales。操作者:

import imp

def make_module_from_text(reader):
    """make a module from file,StringIO, text etc

    Parameters
    ----------
    reader : file_like object
        object to get text from

    Returns
    -------
    m: module
        text as module

    """
    #for making module out of strings/files see https://stackoverflow.com/a/7548190/2530083    

    mymodule = imp.new_module('mymodule') #may need to randomise the name; not sure
    exec reader in mymodule.__dict__    
    return mymodule

然后

import textwrap
reader = textwrap.dedent("""\
    import numpy as np

    a = np.array([0,4,6,7], dtype=float)
    a_normalise = a/a[-1]    
    """)

mymod = make_module_from_text(reader)
print(mymod.a_normalise)

给出

[ 0.          0.57142857  0.85714286  1.        ]

到目前为止一切顺利,但是如果我不相信输入,那么看了看它似乎正在使用python evalexec引入安全漏洞。常见的回答是“永远不要使用eval or执行;它们是邪恶的”,但我真的很喜欢执行代码的强大功能和灵活性。使用{'__builtins__': None}我认为不会对我有用,因为我想导入其他模块(例如我上面代码中的import numpy as np)。许多人(例如here)建议使用ast模块,但我对如何使用它并不是很清楚(可以astexec一起使用吗?) 。是否有简单的方法将白名单/允许特定功能(例如here)?是否有简单的方法来列出/禁止特定功能?是否有一种神奇的方式来执行此操作但不要做任何令人讨厌的事情。

基本上有哪些选项可以确保exec不会运行任何讨厌的恶意代码?

修改

上面我在输入/配置文件中规范化数组的例子可能有点简单,我想在我的输入/配置文件中执行什么计算(我可以在我的程序中轻松编写方法/函数)那)。但是说我的程序在不同的时间计算一个属性。用户需要以某种方式指定时间。我是否应该只接受显式时间值列表,以便用户在准备输入文件之前必须进行一些计算? (注意:即使使用列表作为配置变量也不是一件容易的see here)。我认为这是非常有限的。我应该允许开始 - 结束步骤值,然后在我的程序中使用numpy.linspace吗?我认为这也是限制;我想用numpy.logspace代替吗?如果我有一些函数可以接受重要时间值列表然后很好地填充其他时间以获得间隔时间值,该怎么办?用户能够导入该功能并使用它不是很好吗?如果我想输入用户定义对象列表怎么办?问题是,当我和我的用户已经使用python的功能时,我不想为所有这些特定情况编码。一旦我接受我确实想要在我的输入/配置文件中执行代码的功能和功能,我想知道在使用exec vs使用importlib vs {{ 3}}等等。对我来说,有一个有限的标准配置程序或所有强大的,所有危险的exec。我只是希望有一些中间立场,我可以说'执行此操作......不用填满我的电脑'。

2 个答案:

答案 0 :(得分:3)

“永远不要使用eval或exec;它们是邪恶的”。我认为这是唯一有效的答案。在不受信任的字符串或文件上使用exec / eval没有完全安全的方法。

你能做的最好的事情就是提出自己的语言,或者自己解释一下,或者在处理exec之前把它变成安全的Python代码。小心从头开始 - 如果你允许整个Python语言减去你认为危险的特定事物,它将永远不会真正安全。

例如,如果你想要类似Python的语法,可以使用ast模块;然后编写一个小的自定义ast解释器,它只识别所有可能节点的一小部分。这是最安全的解决方案。

答案 1 :(得分:0)

如果您愿意使用PyPy,那么它的sandboxing feature专门用于运行不受信任的代码,因此它可能对您的情况有用。请注意,提到CPython互操作性存在一些问题,您可能需要检查。

此外,此页面上还有一个名为pysandbox的废弃项目链接,直接在python中解释problems with sandboxing