2

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

基于this SO answer for how to import a string as a module 我编写了以下函数来将字符串或oen文件对象或STringIO作为模块导入。然后我可以使用 . 操作员:

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.        ]

到目前为止一切都很好,但是环顾四周似乎使用 pythoneval并且exec如果我不信任输入会引入安全漏洞。一个常见的回答是“永远不要使用eval orexec;它们是邪恶的”,但我真的很喜欢执行代码的强大功能和灵活性。使用{'__builtins__': None}我不认为对我有用,因为我想导入其他模块(例如import numpy as np在我上面的代码中)。许多人(例如这里)建议使用该ast模块,但我完全不清楚如何使用它(可以astexec?一起使用)。是否有简单的方法来白名单/允许特定功能(例如这里)? 是否有简单的方法将特定功能列入黑名单/禁止?有没有一种神奇的方式可以说执行这个但不要做任何讨厌的事情。

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

编辑:

我上面关于在我的输入/配置文件中规范化数组的示例对于我想要在我的输入/配置文件中执行的计算可能有点简单(我可以很容易地在我的程序中编写一个方法/函数来做到这一点)。但是假设我的程序在不同时间计算一个属性。用户需要以某种方式指定时间。我是否应该只接受一个明确的时间值列表,以便用户在准备输入文件之前必须进行一些计算?(注意:即使使用列表作为配置变量也不是微不足道的,请参见此处)。我认为这是非常有限的。我应该允许 start-end-step 值然后numpy.linspace在我的程序中使用吗?我认为这也有限制;如果我想用怎么办numpy.logspace反而?如果我有一些函数可以接受重要时间值的列表,然后很好地填充其他时间以获得间隔时间值。用户能够导入该功能并使用它不是很好吗?如果我想输入用户定义的对象列表怎么办?问题是,当我和我的用户已经可以使用 python 的功能时,我不想为所有这些特定情况编写代码。一旦我接受我确实想要在我的输入/配置文件中执行代码的能力和功能,我想知道在使用execvs using importlibvs imp.load_source是否真的有任何区别,安全方面等等。对我来说,有有限的标准 configparser 或全能、全危险的 exec。我只是希望有一些中间立场,我可以说'执行这个......而不用填满我的电脑'。

4

2 回答 2

3

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

您能做的最好的事情就是提出自己的语言,然后自己解释或将其转换为安全的 Python 代码,然后再将其处理为 exec。小心从头开始——如果你允许整个 Python 语言减去你认为危险的特定事物,它永远不会真正安全。

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

于 2013-11-01T10:37:04.970 回答
0

如果您愿意使用 PyPy,那么它的沙盒功能是专门为运行不受信任的代码而设计的,因此它可能对您有用。请注意,提到的 CPython 互操作性存在一些问题,您可能需要检查。

此外,此页面上有一个名为 pysandbox 的废弃项目的链接,它解释了直接在 python 中进行沙盒处理的问题。

于 2013-11-26T08:37:57.607 回答