Python函数“compile”和“compiler.parse”是否安全(沙盒)?

时间:2010-10-18 22:51:57

标签: python security

我打算在网络环境中使用这些功能,所以我担心的是这些功能是否可以被利用并用于在服务器上执行恶意软件。

编辑:我不执行结果。我解析AST树和/或捕获SyntaxError。

这是有问题的代码:

try:
    #compile the code and check for syntax errors
    compile(code_string, filename, "exec")
except SyntaxError, value:
    msg = value.args[0]

    (lineno, offset, text) = value.lineno, value.offset, value.text

    if text is None:
        return [{"line": 0, "offset": 0, 
            "message": u"Problem decoding source"}]

    else:
        line = text.splitlines()[-1]

        if offset is not None:
            offset = offset - (len(text) - len(line))
        else:
            offset = 0

        return [{"line": lineno, "offset": offset, "message": msg}]

else:
    #no syntax errors, check it with pyflakes
    tree = compiler.parse(code_string)
    w = checker.Checker(tree, filename)
    w.messages.sort(lambda a, b: cmp(a.lineno, b.lineno))

checker.Checker是解析AST树的pyflakes类。

5 个答案:

答案 0 :(得分:4)

我认为更有趣的问题是你在编译函数时做了什么?运行它们肯定是不安全的。

我已经测试过我能想到的几个漏洞,因为它只是一个语法检查器(无法重新定义类/函数等)我不会认为无论如何都要将python转换为在编译时执行任意代码

答案 1 :(得分:2)

如果攻击者可以控制其输入并执行输出,则

compiler.parsecompile绝对可以用于攻击。在大多数情况下,您要输出evalexec以使其运行,因此这些仍然是常见的嫌疑人,compilecompiler.parse(已弃用的BTW)是只是在恶意输入和执行之间添加另一个步骤。

编辑:刚看到您留下了一条评论,表明您实际上正计划在 USER INPUT 上使用这些评论。不要那样做。或者至少,不要实际执行结果。对于那些最终运行该代码的人来说,这是一个巨大的安全漏洞。如果没有人会运行它,为什么要编译呢?因为你澄清了你只想检查语法,这应该没问题。我不会存储输出,因为没有理由让潜在的攻击者更轻松,并且能够在系统上获得任意代码是第一步。

如果你确实需要存储它,我可能会喜欢类似于通常用于图像的方案,它们以不可预测的方式重命名,并增加了确保它不存储在导入路径中的步骤

答案 2 :(得分:2)

如果永远不会评估生成的代码或AST对象,我认为您只受到DDoS攻击。

如果您正在评估用户输入的代码,则与向每个用户提供作为网络服务器用户的shell访问权限相同。

答案 3 :(得分:2)

他们不是,但找到一个可以沙箱到一定程度的Python子集并不是一件难事。如果你想走这条路,你需要自己解析那个Python子集,并拦截所有调用,属性查找和其他所有相关内容。您也不希望授予用户访问任何语言结构的权限,例如未终止循环等。

还有兴趣吗?前往jinja2.sandbox:)

答案 4 :(得分:1)

是的,他们可能被恶意利用。

如果你真的想要安全的沙盒,你可以看看PyPy's sandboxing features,但要注意沙盒并不容易,并且可能有更好的方法来完成你想要的任何东西。

校正

由于您已经更新了问题,以澄清您只是将不受信任的输入解析为AST,因此无需沙箱任何内容:沙盒专门用于执行不受信任的代码(大多数人可能假设你的目标是,通过询问沙盒)。

仅使用compile / compiler进行解析应该是安全的:Python源解析没有任何钩子进入代码执行。 (请注意,并非所有语言都适用:例如,在没有代码执行的情况下无法(完全)解析Perl。)

唯一剩下的风险是有人可能能够制作一些病态的Python源代码,使其中一个解析器使用大量的内存/处理器时间,但资源耗尽攻击会影响一切,所以你只想要在必要时管理这个。 (例如,如果您的部署是关键任务且无法承受具有病态源代码的攻击者的拒绝服务,则可以在resource-limited子进程中执行解析。)