2010-01-03 38 views
3

我正在建立一个网站,我有一个需要,用户应该能够评估一些表达式基于数据库表中的值,而不是使用像pyparsing等工具,我正在考虑使用python本身,并且已经想出了一个足以达到我的目的的解决方案。我基本上使用eval来评估表达式并传递全局空字符__builtins__,这样就不会有任何东西可以被访问,并且当地人从DB中得到值,如果用户需要某些函数,我也可以通过这些函数。使用eval进行表达式评估安全性如何?

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. 我的程序或表格等someshow的用户访问当前的状态可以吗?
  2. 用户可以访问os级别的调用吗?
  3. 用户可以通过循环或使用大量内存来暂停我的系统,例如通过做范围(10 * 8),在某些情况下,他可以例如100 ** 1000等等,所以3不是一个问题。我可以使用标记来检查这样的操作,无论如何,我将使用GAE,所以它不是很关心。

编辑:IMO这不是Q:661084重复的,因为在那里结束这一个开始,我想知道,即使__builtins__堵塞,用户可以做坏事?

+0

检查:http:// stackoverflow。com/questions/661084/pythons -eval-on-untrusted-strings – fserb 2010-01-03 05:36:19

+0

@fserb查看编辑 – 2010-01-03 05:40:59

回答

7

它是完全不安全使用eval,甚至内置插件清空受阻 - 攻击者可以用文字开始,得到它的__class__,等,等,多达object,其__subclasses__,等等...基本上,Python内省太强大,无法站立给一个熟练的,坚定的攻击者。

ast.literal_eval安全的,如果你可以通过它的局限性住...

+1

好吧我相信你:)但一些反例将是有趣的,无论如何,我会尝试PyParsing然后。 – 2010-01-03 06:49:11

+1

你可以到任何*类型或类(通过'__class__'和'__mro__'或'__bases__',然后通过'__subclasses__'向下移动到'object')的提示应该是足够的作为“反例”:让想要发挥破坏性恶作剧的恶意黑客至少花一分钟时间构建解决方案......!) – 2010-01-03 16:39:19

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的方法?他们怎么了?

+0

是设置__builtins__变量,限制执行模式踢入:) – 2010-01-03 05:52:04

+0

+1对'restricted attribute'我不知道看起来像是由于旧的reexec模块,我想使用eval,因为如果我可以为什么不呢? – 2010-01-03 05:59:19

2

它有可能获得创建和调用的程序,其中包括那些可以退出Python解释器中定义的任何类。另外,你可以创建并执行任意字节码字符串,这可以对解释器进行段错误。所有的细节见Eval really is dangerous