繁体   English   中英

使用ast和白名单使python的eval()安全吗?

[英]Using ast and whitelists to make python's eval() safe?

好。 知道 专家 ,你不应该永远使用Python eval()在不可信的数据,直到永远。 我并不比世界其他地方更聪明,甚至不应该尝试这个。 但! 无论如何,我要去。

我的基本问题是我正在编写一个小计算器评估程序,它将使用python语法的一个子集进行不可信的输入。 我知道:使用plypyparsing并编写解析器然后我们去。 通过将全局变量和局部变量传递给eval()来解决这个问题是不行的。

我所看到的所有方法(并且一直保持冷漠)试图列举邪恶。 在这里,我试图枚举 - 得到一个AST,只允许几个节点类型,然后验证任何调用是否属于一组白名单函数之一。 这是一个迷你实现(和要点 ):

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__或任何东西。

我......我觉得这很有效。 我疯了吗?

尝试asteval ,看起来像你需要的东西。 否则就有这个安全评估

Zope有一个名为RestrictedPython的东西,您可能想检查它,至少是为了验证您的方法或可能重用它们的代码。 它是可配置和可重用的。

这是对类似问题的另一个答案

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM