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

时间:2010-01-03 05:23:20

标签: python security eval

我正在构建一个网站,我需要用户能够根据数据库表中的值来评估某些表达式,而不是使用像pyparsing等工具,我正在考虑使用python本身,并且已经出现了用一个足以满足我的目的的解决方案。我基本上使用eval来评估表达式并使用空__builtins__传递全局变量dict,这样就无法访问任何内容并且本地数据来自DB的值,如果用户需要一些函数我也可以传递它们,例如

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})

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

  1. 用户可以访问我的程序或表等的当前状态吗?
  2. 用户可以访问操作系统级别的电话吗?
  3. 用户可以通过循环或使用大量内存来暂停我的系统,例如通过做范围(10 * 8),在某些情况下,他可以例如100 ** 1000等,所以3不是一个问题。我可以使用tokenize检查这样的操作,无论如何我将使用GAE,所以它不是很关心。
  4. 修改:IMO这不是Q:661084的副本,因为它结束了这个开始,我想知道即使__builtins__被阻止,用户也可以做坏事?

3 个答案:

答案 0 :(得分:7)

使用eval是完全不安全的,即使内置文件被清空和阻止 - 攻击者可以从文字开头,获取__class__等等,直至{{1} },它的object等等...基本上,Python内省太强大了,无法与熟练的,坚定的攻击者对抗。

ast.literal_eval 是安全的,如果你可以忍受它的限制......

答案 1 :(得分:4)

当然,即使没有内置,也可以使用所有可用内存或创建无限循环。有很多方法可以做到这一点,例如'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的方法?他们有什么问题?

答案 2 :(得分:2)

可以创建并调用程序中定义的任何类,其中包括可以退出Python解释器的类。此外,您可以创建和执行任意字节码字符串,这可能会使解释器发生段错误。有关所有详细信息,请参阅Eval really is dangerous