Python 的 eval() 对不可信字符串的安全性?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/661084/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 20:34:25  来源:igfitidea点击:

Security of Python's eval() on untrusted strings?

pythonsecurityeval

提问by Jerub

If I am evaluating a Python string using eval(), and have a class like:

如果我正在使用 eval() 评估 Python 字符串,并且有一个类似的类:

class Foo(object):
    a = 3
    def bar(self, x): return x + a

What are the security risks if I do not trust the string? In particular:

如果我不信任该字符串,会有什么安全风险?特别是:

  1. Is eval(string, {"f": Foo()}, {})unsafe? That is, can you reach os or sys or something unsafe from a Foo instance?
  2. Is eval(string, {}, {})unsafe? That is, can I reach os or sys entirely from builtins like len and list?
  3. Is there a way to make builtins not present at all in the eval context?
  1. eval(string, {"f": Foo()}, {})不安全的?也就是说,你能从 Foo 实例访问 os 或 sys 或不安全的东西吗?
  2. eval(string, {}, {})不安全的?也就是说,我可以完全从 len 和 list 等内置函数访问 os 或 sys 吗?
  3. 有没有办法让内置函数在 eval 上下文中根本不存在?

There are some unsafe strings like "[0] * 100000000" I don't care about, because at worst they slow/stop the program. I am primarily concerned about protecting user data external to the program.

有一些不安全的字符串,例如“[0] * 100000000”,我不在乎,因为最坏的情况是它们会减慢/停止程序。我主要关心保护程序外部的用户数据。

Obviously, eval(string)without custom dictionaries is unsafe in most cases.

显然,eval(string)在大多数情况下,没有自定义词典是不安全的。

采纳答案by Ned Batchelder

You cannot secure eval with a blacklist approach like this. See Eval really is dangerousfor examples of input that will segfault the CPython interpreter, give access to any class you like, and so on.

您无法使用这样的黑名单方法来保护 eval。对于将导致 CPython 解释器出现段错误、允许访问您喜欢的任何类等的输入示例,请参阅Eval 确实是危险的

回答by Jerub

eval()will allow malicious data to compromise your entire system, kill your cat, eat your dog and make love to your wife.

eval()将允许恶意数据危害您的整个系统,杀死您的猫,吃掉您的狗并与您的妻子做爱。

There was recently a thread about how to do this kind of thing safely on the python-dev list, and the conclusions were:

最近在python-dev列表上有一个关于如何安全地做这种事情的线程,得出的结论是:

  • It's really hard to do this properly.
  • It requires patches to the python interpreter to block many classes of attacks.
  • Don't do it unless you really want to.
  • 正确地做到这一点真的很难。
  • 它需要对 python 解释器打补丁来阻止许多类型的攻击。
  • 除非你真的想要,否则不要这样做。

Start here to read about the challenge: http://tav.espians.com/a-challenge-to-break-python-security.html

从这里开始阅读挑战:http: //tav.espians.com/a-challenge-to-break-python-security.html

What situation do you want to use eval() in? Are you wanting a user to be able to execute arbitrary expressions? Or are you wanting to transfer data in some way? Perhaps it's possible to lock down the input in some way.

你想在什么情况下使用 eval()?您是否希望用户能够执行任意表达式?或者您想以某种方式传输数据?也许有可能以某种方式锁定输入。

回答by John Fouhy

You can get to osusing builtin functions: __import__('os').

您可以开始os使用内置函数:__import__('os').

For python 2.6+, the ast modulemay help; in particular ast.literal_eval, although it depends on exactly what you want to eval.

对于 python 2.6+,ast 模块可能会有所帮助;特别是ast.literal_eval,尽管这取决于您想要评估的内容。

回答by Benjamin Peterson

Note that even if you pass empty dictionaries to eval(), it's still possible to segfault (C)Python with some syntax tricks. For example, try this on your interpreter: eval("()"*8**5)

请注意,即使您将空字典传递给 eval(),仍然可以使用一些语法技巧对 (C)Python 进行段错误。例如,在你的解释器上试试这个:eval("()"*8**5)

回答by MarkusQ

You are probably better off turning the question around:

你最好把问题转过来:

  1. What sort of expressions are you wanting to eval?
  2. Can you insure that only strings matching some narrowly defined syntax are eval()d?
  3. Then consider if thatis safe.
  1. 你想评估什么样的表达式?
  2. 你能确保只有匹配某些狭义语法的字符串才是 eval()d 吗?
  3. 然后考虑如果是安全的。

For example, if you are wanting to let the user enter an algebraic expression for evaluation, consider limiting them to one letter variable names, numbers, and a specific set of operators and functions. Don't eval() strings containing anything else.

例如,如果您想让用户输入代数表达式进行计算,请考虑将它们限制为一个字母的变量名称、数字以及一组特定的运算符和函数。不要 eval() 包含任何其他内容的字符串。

回答by Tim Pietzcker

There is a very good article on the un-safety of eval()in Mark Pilgrim's Dive into Pythontutorial.

Mark Pilgrim 的Dive into Python教程中有一篇关于不安全性的eval()非常好的文章

Quoted from this article:

引自这篇文章:

In the end, it is possible to safely evaluate untrusted Python expressions, for some definition of “safe” that turns out not to be terribly useful in real life. It's fine if you're just playing around, and it's fine if you only ever pass it trusted input. But anything else is just asking for trouble.

最后,可以安全地评估不受信任的 Python 表达式,因为某些“安全”的定义在现实生活中并不是非常有用。如果你只是在玩,那很好,如果你只传递可信的输入也很好。但其他任何事情都只是自找麻烦。