【问题标题】:Using ast and whitelists to make python's eval() safe?使用 ast 和白名单使 python 的 eval() 安全?
【发布时间】:2012-09-21 02:34:47
【问题描述】:

好的。我knowtheexpertshavespoken,你不应该永远在不受信任的数据上使用python的eval(),永远。我并不比世界其他人聪明,甚至不应该尝试这个。但!不管怎样,我要去。

我的基本问题是,我希望使用 python 语法的子集编写一个小型计算器评估程序,该程序将接受不受信任的输入。我知道:使用plypyparsing 并编写一个解析器就可以了。将全局变量和局部变量传递给 eval() 是不行的。

我见过的所有方法(并且一直持怀疑态度)都试图列举邪恶。在这里,我试图枚举 good —— 获取一个 AST,只允许少数节点类型,然后验证任何调用都是针对一组白名单函数中的一个。这是一个小实现(和a gist):

import ast
import math

SAFE_FX = {
    'exp': math.exp,
}

SAFE_NODES = set(
    (ast.Expression,
    ast.Num,
    ast.Call,
    ast.Name,
    ast.Load,
    ast.BinOp,
    ast.Add,
    ast.Sub,
    ast.Mult,
    ast.Div,)
)

class CleansingNodeVisitor(ast.NodeVisitor):
    def generic_visit(self, node):
        if type(node) not in SAFE_NODES:
            raise Exception("%s not in SAFE_NODES" % type(node))
        super(CleansingNodeVisitor, self).generic_visit(node)

    def visit_Call(self, call):
        if call.func.id not in SAFE_FX:
            raise Exception("Unknown function: %s" % call.func.id)

def my_safe_eval(s):
    tree = ast.parse(s, mode='eval')
    cnv = CleansingNodeVisitor()
    cnv.visit(tree)
    compiled = compile(tree, s, "eval")
    return(eval(compiled, SAFE_FX))

所以,my_safe_eval('2*(4+exp(1.3))') 有效,而 my_safe_eval('[].__class__') 诡计和 my_safe_eval('open("/something/evil")') 同样被禁止 - 没有禁止 __builtins____locals__ 或任何东西。

我...我认为这行得通。我疯了吗?

【问题讨论】:

标签: python security parsing eval


【解决方案1】:

Zope 有一个叫做RestrictedPython 的东西,你可能想检查一下,至少是为了验证你的方法或者可能重用他们的代码。它是可配置和可重复使用的。

这里是my other answer 来回答类似的问题。

【讨论】:

  • RestrictedPython 看起来很整洁,但是,它很大。我真的只想安全地支持python语法的一小部分,并且只支持评估表达式和一组有限的函数调用。我不认为沙盒 python 真的是我想要的。不能完全说出原因。
  • 很好,但是例如如何处理while True:pass
【解决方案2】:

试试asteval,好像是你需要的东西。 否则有这个safe eval

【讨论】:

  • 我也在看asteval,很想听听人们的意见。 @Nate 您是否针对它对代码进行了基准测试?你尝试过ned batchelder's post 上的所有漏洞吗?很高兴看到人们对此采取行动!
  • asteval 不能被利用,因为它非常有限,并且在 AST 级别被删除。我不得不为我的项目放弃它,因为它是有限的。我使用了 spydermonkey 和 pyv8 .. 但这是在 2 种不同语言之间进行上下文切换的重载。所以我最终要么使用 pypy,要么只是删除 eval 功能,用简单的解析器替换它们——最好的决定。大多数时候你不需要图灵完备性......
猜你喜欢
  • 1970-01-01
  • 2017-11-23
  • 1970-01-01
  • 2020-05-13
  • 1970-01-01
  • 2016-12-27
  • 2023-03-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多