关于Python中的“eval is evil”和“同意成年人”

时间:2014-03-03 06:55:35

标签: python conventions duck-typing

我看到很多人说"eval is evil/dangerous/insecure",因为人们可以这样做:

eval("os.system('rm -rf /')")

other posts中,pythoner被认为是“同意成人”,你不必进行类型检查,因为python的样式是 duck typing

那么下面的代码如何:

def foo(duck):
    duck.quack()

class EvilDuck(object):
    def quack(self):
        os.system('rm -rf /')

foo(EvilDuck())

你通常如何避免这种情况?蟒蛇人何时同意成年人,何时不同意?

3 个答案:

答案 0 :(得分:19)

eval是邪恶的,因为用户输入会在某个时刻进入它。你没有(好吧,不应该)担心代码假装不删除所有文件,因为代码可以做到这一点 - tada:

def foo(duck):
    duck.quack()

class EvilDuck(object):
    os.system('rm -rf /')

    def quack(self):
        pass

rm -rf /很有可能无法正常工作。 ;)

基本上,“同意成年人”是“相信你的代码”。 eval是“信任所有代码”。根据您获得该代码的位置,eval可以很好,但99%的时间都没有必要,而且也很难保证安全。

答案 1 :(得分:5)

对于Python来说,试图阻止他们从他们的程序执行命令,他们可以直接输入shell命令行而不涉及Python,这似乎很愚蠢。

鸭子打字没问题,因为它不涉及运行J. Random internet-User编写的代码。您(大概)可以按照与其预期用途一致的方式调用您定义的对象。

eval()exec(也是Python 3中的函数,但Python 2中的一个语句)在应用于经过充分验证的用户输入时被认为是危险的,因为没有验证你对自己的恶意用户群的意志持开放态度。

换句话说,像

这样的代码
eval(raw_input("How may I hack you today? "))

很危险,因为用户可能选择输入

os.system("switch off your antivirus protection")

或类似涉及风险的其他事情。

答案 2 :(得分:3)

顶部

  

在Python中使用eval是一种不好的做法吗?

回答给出了eval不好的4个原因

  1. 几乎总有一种更好的方法可以做到这一点
  2. 非常危险和不安全
  3. 使调试变得困难
  4. 从安全的角度来看,

    eval特别糟糕,如果字符串的任何部分是从用户输入中提取的,并且清理不受信任的用户输入/尝试保护eval通常毫无价值,但正如其他人提到的那样同类中唯一的错误。从pickle或json / yml / xml中反序列化不受信任/用户输入,包括反序列化任意对象,也存在类似的安全问题。

    作为参数1/3/4指出eval通常被认为是一个次优的解决方案,即使除了通常可以避免的安全问题(通过不使用它与用户输入生成的字符串)有一点考虑(虽然这可以当它是一个很容易错过的实现细节时会出现问题。

    如果可能的话,通常认为使用其他python功能实现相同的功能会更好的代码/更易于维护。

    然而它可能很有用,std库中的namedtuple是使用~~ eval ~~ exec实现的(类似)。

    其他人提到与goto的比较,这在某些方面也“太强大”,但可能非常有用(但仅限于c)。

    我已经用它来为我的代码开发有用的调试函数和ruby,就像字符串插值一样。