Python的eval()在不受信任的string上的安全性?
如果我正在使用eval()来评估一个Pythonstring,并且有一个如下所示的类:
class Foo(object): a = 3 def bar(self, x): return x + a
如果我不信任string,有什么安全风险? 尤其是:
- 是
eval(string, {"f": Foo()}, {})
不安全? 也就是说,你可以达到OS或SYS或从Foo实例不安全? -
eval(string, {}, {})
不安全? 也就是说,我可以完全从内置的len和list到os或sys吗? - 有没有一种方法可以让内置的东西在评估环境中不存在?
有一些不安全的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)
你可能会更好地解决这个问题:
- 你想要评价什么样的表情?
- 你能保证只有匹配一些狭义的语法的string是eval()d吗?
- 然后考虑这是否安全。
例如,如果要让用户input代数expression式进行评估,请考虑将其限制为一个字母variables名称,数字以及特定的一组运算符和函数。 不要eval()包含任何其他的string。
关于Mark Pilgrim的“ 潜入Python教程” 中eval()
的非安全性,有一篇很好的文章 。
引用这篇文章:
最后,可以安全地评估不可信的Pythonexpression式,因为对于“安全”的一些定义在现实生活中并不是非常有用。 如果你只是在玩游戏,这很好,如果你只传递可信任的input,那也没关系。 但其他任何事情都只是要求麻烦。