29

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

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

如果我不信任该字符串,会有哪些安全风险?尤其:

  1. eval(string, {"f": Foo()}, {})不安全吗?也就是说,您可以从 Foo 实例访问 os 或 sys 或不安全的东西吗?
  2. eval(string, {}, {})不安全吗?也就是说,我可以完全从 len 和 list 等内置函数访问 os 或 sys 吗?
  3. 有没有办法让内置函数在 eval 上下文中根本不存在?

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

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

4

6 回答 6

53

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

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

  • 正确地做到这一点真的很难。
  • 它需要python解释器的补丁来阻止许多类型的攻击。
  • 除非你真的想要,否则不要这样做。

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

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

于 2009-03-19T05:13:44.763 回答
19

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

于 2012-06-09T20:28:25.967 回答
12

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

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

于 2009-03-19T21:55:19.187 回答
7

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

于 2009-03-19T20:36:24.740 回答
4

你最好把这个问题转过来:

  1. 你想要评估什么样的表达式?
  2. 你能确保只有匹配某些狭义语法的字符串是 eval()d 吗?
  3. 然后考虑是否安全

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

于 2009-03-19T05:57:13.223 回答
2

在 Mark Pilgrim 的Dive into Python教程中有一篇很好的关于不安全的文章。eval()

引用自这篇文章:

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

于 2010-01-03T10:14:40.817 回答