使用ast和白名单使python的eval()安全吗? [英] Using ast and whitelists to make python's eval() safe?

查看:125
本文介绍了使用ast和白名单使python的eval()安全吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好.我知道 专家 拥有

OK. I know the experts have spoken and you should not ever use python's eval() on untrusted data, ever. I'm not smarter than the rest of the world, and shouldn't even try this. But! I'm going to, anyhow.

我的基本问题是我希望编写一个小的计算器评估程序,该程序将使用python语法的子集来接受不受信任的输入.我知道:使用 ply

My basic problem is that I'm looking to write a little calculator evaluator program that'll take untrusted input, using a subset of python's syntax. I know: use ply or pyparsing and write a parser and there we go. Screwing around with passing globals and locals to eval() will not do the trick.

我已经看到(并且一直持怀疑态度)的所有方法都试图枚举邪恶.在这里,我试图枚举 good -获得AST,仅允许几种节点类型,然后验证是否所有调用都属于一组列入白名单的函数.这是一个微型实现(和要点):

All the approaches I've seen (and been leery about) try to enumerate evil. Here, I'm trying to enumerate good -- get an AST, allow only a few node types, and then verify that any calls are to one of a set of whitelisted functions. Here's a mini-implementation (and 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__或其他任何东西.

So, my_safe_eval('2*(4+exp(1.3))') works, while my_safe_eval('[].__class__') tricks and my_safe_eval('open("/something/evil")') is likewise forbidden -- without forbidding __builtins__ or __locals__ or anything.

我...我认为这可行.我生气了吗?

I... I think this works. Am I mad?

推荐答案

尝试 asteval ,你需要的东西. 否则,将出现安全评估

Try asteval, seems like the thing you need. Otherwise there is this safe eval

这篇关于使用ast和白名单使python的eval()安全吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆