Python:如何安全使用eval

60 投票
4 回答
53095 浏览
提问于 2025-04-16 02:58

我想在Python中简单地做一个“计算器API”。

现在我并不太在乎这个计算器具体要支持哪些功能。

我希望它能接收一个字符串,比如 "1+1",然后返回一个字符串,结果是 "2"

有没有办法让 eval 在这种情况下变得安全呢?

首先,我会这样做:

env = {}
env["locals"]   = None
env["globals"]  = None
env["__name__"] = None
env["__file__"] = None
env["__builtins__"] = None

eval(users_str, env)

这样调用者就不能随意修改我的本地变量(或者看到它们)。

但我知道我可能忽略了很多东西。

那么,eval 的安全问题能解决吗?还是说有太多小细节让它很难做到正确?

4 个回答

1

安全问题几乎是无法解决的。

我会使用pyparsing这个库来把表达式解析成一个个小的部分(这应该不太难,因为它的语法很简单),然后再逐个处理这些部分。

你也可以使用ast模块来构建一个Python的抽象语法树(AST),因为你使用的是有效的Python语法,但这样可能会存在一些微妙的安全隐患。

15

你可以访问在程序中定义的任何类,然后你可以创建这个类的实例并调用它的方法。这样做有可能会导致CPython解释器崩溃,或者让它退出。想了解更多,可以看看这个链接:Eval真的很危险

78

eval的安全问题能解决吗,还是说有太多小细节让它难以正确工作?

肯定是后者——聪明的黑客总能找到绕过你防护的方法。

如果你只需要使用简单的表达式和基本类型的字面量,可以使用 ast.literal_eval ——这就是它的用途!如果你需要更复杂的功能,我推荐使用解析包,比如如果你熟悉传统的lex/yacc方法,可以试试 ply,或者如果你想要更符合Python风格的方式,可以考虑 pyparsing

撰写回答