使用 eval 进行表达式评估有多安全?

Posted

技术标签:

【中文标题】使用 eval 进行表达式评估有多安全?【英文标题】:How safe is expression evaluation using eval? 【发布时间】:2010-12-31 22:22:50 【问题描述】:

我正在建立一个网站,我需要用户应该能够根据 DB 表中的值评估一些表达式,而不是使用 pyparsing 等工具,我正在考虑使用 python 本身,并且已经提出有一个足以满足我目的的解决方案。我基本上是使用 eval 来评估表达式并使用空的__builtins__ 传递全局字典,这样就可以访问任何内容,并使用本地字典来获取数据库中的值,如果用户需要一些函数,我也可以传递这些函数,例如

import datetime
def today():
    return datetime.datetime.now()

expression = """ first_name.lower() == "anurag" and today().year == 2010 """

print eval(expression, '__builtins__':, 'first_name':'Anurag', 'today':today)

所以我的问题是它有多安全,我有三个标准

    用户可以访问我的程序或表等的当前状态吗? 用户可以访问操作系统级别的调用吗? 用户可以通过循环或使用大量内存来暂停我的系统,例如通过执行 range(10*8),在某些情况下,他可以例如 100**1000 等,所以 3 并不是什么大问题。我可以用 tokenize 检查这样的操作,无论如何我将使用 GAE,所以这不是什么大问题。

编辑:IMO这不是Q:661084的副本,因为它从哪里开始,我想知道即使__builtins__被屏蔽,用户可以做坏事吗?

【问题讨论】:

检查:***.com/questions/661084/… 【参考方案1】:

使用eval 是完全不安全的,即使内置程序被清空和阻止——攻击者可以从文字开始,获取它的__class__ 等等,直到object,它的__subclasses__等等……基本上,Python 的自省功能太强大了,无法抵御熟练、坚定的攻击者。

ast.literal_eval 安全的,如果你能忍受它的限制......

【讨论】:

好的,我相信你 :) 但是一些反例会很有趣,无论如何我会尝试 PyParsing。 你可以得到any类型或类的提示(通过向上移动到object,例如通过__class____mro____bases__,然后向下移动via __subclasses__, ...) 应该足以作为“反例”:让想要玩破坏性恶作剧的恶意黑客至少花一分钟时间来构建他们的解决方案...!-)【参考方案2】:

当然,即使没有内置函数,也可以消耗所有可用内存或创建无限循环。有很多方法可以做到这一点,例如 'a'*999999*999999 或进行无限循环:

>>> print eval('[[x.append(a) for a in x] for x in [[0]]]',
...             '__builtins__':, 'first_name':'Anurag', 'today':today)

至于 1) 和 2),我不确定,但看起来有风险。这是我尝试过的一件我认为可行的事情,但似乎其他人已经考虑过该攻击线并阻止了它:

>>> import datetime
>>> def today():
>>>     return datetime.datetime.now()
>>>
>>> print eval('today.func_globals', '__builtins__':, 'first_name':'Anurag', 'today':today)
RuntimeError: restricted attribute

我有一半希望得到这个:

'__builtins__': <module '__builtin__' (built-in)>, ...

所以我认为这可能是个坏主意。您只需要一个小孔,就可以访问整个系统。您是否考虑过其他不使用 eval 的方法?他们有什么问题?

【讨论】:

是设置 builtins 变量,限制执行模式启动:) +1 for 'restricted attribute' 我不知道,看起来是由于旧的 reexec 模块,我想使用 eval 因为如果我可以为什么不呢?【参考方案3】:

可以创建和调用程序中定义的任何类,包括可以退出 Python 解释器的类。此外,您可以创建和执行任意字节码字符串,这可能会导致解释器出现段错误。详情请见Eval really is dangerous。

【讨论】:

以上是关于使用 eval 进行表达式评估有多安全?的主要内容,如果未能解决你的问题,请参考以下文章

从 Pandas 中的公式动态评估表达式

C++ Exprtk 与 Python eval()

评估作为字符串给出的表达式

Scala中的“评估”

使用多态性的表达式评估和树行走? (阿拉史蒂夫耶格)

评估复合程序元循环“应用”的顺序