Python的eval()在不受信任的string上的安全性?

如果我正在使用eval()来评估一个Pythonstring,并且有一个如下所示的类:

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

如果我不信任string,有什么安全风险? 尤其是:

  1. eval(string, {"f": Foo()}, {})不安全? 也就是说,你可以达到OS或SYS或从Foo实例不安全?
  2. eval(string, {}, {})不安全? 也就是说,我可以完全从内置的len和list到os或sys吗?
  3. 有没有一种方法可以让内置的东西在评估环境中不存在?

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

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

用这种黑名单方法无法确保eval。 看到Eval确实是危险的input的例子将段错误的CPython解释器,给你访问任何你喜欢的类,等等。

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

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

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

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

你想在什么情况下使用eval()? 你想要一个用户能够执行任意expression式吗? 还是你想以某种方式传输数据? 也许有可能以某种方式lockinginput。

你可以使用内build函数来访问os__import__('os')

对于python 2.6+, ast模块可能会有所帮助; 特别是ast.literal_eval ,虽然它取决于你想要评估的东西。

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

你可能会更好地解决这个问题:

  1. 你想要评价什么样的表情?
  2. 你能保证只有匹配一些狭义的语法的string是eval()d吗?
  3. 然后考虑是否安全。

例如,如果要让用户input代数expression式进行评估,请考虑将其限制为一个字母variables名称,数字以及特定的一组运算符和函数。 不要eval()包含任何其他的string。

关于Mark Pilgrim的“ 潜入Python教程” 中eval()的非安全性,有一篇很好的文章 。

引用这篇文章:

最后,可以安全地评估不可信的Pythonexpression式,因为对于“安全”的一些定义在现实生活中并不是非常有用。 如果你只是在玩游戏,这很好,如果你只传递可信任的input,那也没关系。 但其他任何事情都只是要求麻烦。