Python的eval()在不受信任的字符串上的安全性?

时间:2009-03-19 04:39:50

标签: python security eval

如果我使用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上下文中的内置函数不存在?
  4. 有一些不安全的字符串,如“[0] * 100000000”我不在乎,因为最坏的情况是他们减慢/停止程序。我主要关心的是保护程序外部的用户数据。

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

6 个答案:

答案 0 :(得分:45)

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

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

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

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

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

答案 1 :(得分:15)

您无法使用此类黑名单方法保护eval。有关输入的示例,请参阅Eval really is dangerous,以便对CPython解释器进行分段,提供对您喜欢的任何类的访问权限等等。

答案 2 :(得分:10)

您可以使用内置函数os来访问__import__('os')

对于python 2.6+,ast module可能有所帮助;特别是ast.literal_eval,虽然它完全取决于你想要评估的内容。

答案 3 :(得分:6)

请注意,即使您将空字典传递给eval(),仍然可以使用一些语法技巧来段落(C)Python。例如,请在解释器上尝试此操作:eval("()"*8**5)

答案 4 :(得分:4)

你最好转过头来解决问题:

  1. 您想要评估哪种表达方式?
  2. 你能确保只有匹配一些狭义语法的字符串才是eval()d?
  3. 然后考虑 是否安全。
  4. 例如,如果您想让用户输入代数表达式进行评估,请考虑将它们限制为一个字母的变量名称,数字和一组特定的运算符和函数。不要eval()包含任何其他内容的字符串。

答案 5 :(得分:2)

Mark Pilgrim的article on the un-safety of eval()教程中有一个非常好的Dive into Python

引自本文:

  

最后,可以安全地进行   评估不受信任的Python表达式,   对于某些“安全”的定义   事实证明并不是非常有用   现实生活。如果你只是,这很好   玩耍,如果你没事的话   只传递信任输入。但   其他任何东西都只是要求   麻烦。