我正在构建一个网站,我需要用户能够根据数据库表中的值来评估某些表达式,而不是使用像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})
所以我的问题是它有多安全,我有三个标准
修改:IMO这不是Q:661084的副本,因为它结束了这个开始,我想知道即使__builtins__
被阻止,用户也可以做坏事?
答案 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。