使用 eval 进行表达式求值有多安全?
我正在建立一个网站,我需要用户应该能够根据数据库表中的值评估一些表达式,而不是使用 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,这不是问的重复: 661084 因为它从哪里结束,这个从哪里开始,我想知道即使 __builtins__
被阻止,用户可以做坏事吗?
I am building a website where I have a need that user should be able to evaluate some expression based from the value in DB tables, instead of using tools like pyparsing etc, I am thinking of using python itself, and have come up with a solution which is sufficient for my purpose. I am basically using eval to evaluate the expression and passing globals dict with empty __builtins__
so that nothing can be accessed and a locals dict for values from DB, if user will need some functions I can pass those too e.g.
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})
So my question is how safe it would be , I have three criteria
- Can user access current state of my program or table etc someshow?
- Can user have access to os level calls?
- Can user halt my system by looping or using much memory e.g. by doing range(10*8), in some cases he can e.g 100**1000 etc so 3 is not so much of a problem. i may check such op with tokenize and anyway I will be using GAE so it is not not much of concern.
Edit: IMO this is not the duplicate of Q:661084 because where it ends this one starts, I want to know even with __builtins__
blocked, can user do bad things?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
使用
eval
是完全不安全的,即使内置函数被清空并被阻止——攻击者可以从一个文字开始,获取它的__class__
等,最多 < code>object,它的__subclasses__
,等等……基本上,Python 的自省功能太强大,无法抵御熟练且坚定的攻击者。ast.literal_eval
是安全的,如果你能忍受它的局限性......It's completely unsafe to use
eval
, even with built-ins emptied and blocked -- the attacker can start with a literal, get its__class__
, etc, etc, up toobject
, its__subclasses__
, and so forth... basically, Python introspection is just too strong to stand up to a skilled, determined attacker.ast.literal_eval
is safe, if you can live by its limitations...当然,即使没有内置函数,也可以消耗所有可用内存或创建无限循环。有很多方法可以做到这一点,例如 'a'*999999*999999 或进行无限循环:
至于 1) 和 2),我不确定,但看起来有风险。这是我尝试过的一件事,我认为会起作用,但似乎其他人已经考虑了这一攻击路线并阻止了它:
我一半期望得到这个:
所以我认为这可能是一个坏主意。您只需要一个小孔就可以访问整个系统。您是否考虑过其他不使用 eval 的方法?他们有什么问题吗?
Certainly it's possible to consume all available memory or create an infinite loop even without the builtins. There are many ways to do it such as 'a'*999999*999999 or to make an infinite loop:
As for 1) and 2), I'm not sure but it looks risky. Here is one thing that I tried that I thought would work, but it seems that someone else already considered that line of attack and blocked it:
I was half expecting to get this instead:
So I think it's probably a bad idea. You only need one tiny hole and you give access to your entire system. Have you considered other methods that don't use eval? What is wrong with them?
可以创建并调用程序中定义的任何类,其中包括可以退出 Python 解释器的类。此外,您可以创建并执行任意字节码字符串,这可能会导致解释器出现段错误。有关所有详细信息,请参阅Eval 确实很危险。
It is possible to get create and invoke any class defined in the program, which includes ones that can exit the Python interpreter. In addition, you can create and execute arbitrary strings of bytecode, which can segfault the interpreter. See Eval really is dangerous for all the details.