我看到很多人说"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())
你通常如何避免这种情况?蟒蛇人何时同意成年人,何时不同意?
答案 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个原因
eval
特别糟糕,如果字符串的任何部分是从用户输入中提取的,并且清理不受信任的用户输入/尝试保护eval通常毫无价值,但正如其他人提到的那样同类中唯一的错误。从pickle或json / yml / xml中反序列化不受信任/用户输入,包括反序列化任意对象,也存在类似的安全问题。
作为参数1/3/4指出eval通常被认为是一个次优的解决方案,即使除了通常可以避免的安全问题(通过不使用它与用户输入生成的字符串)有一点考虑(虽然这可以当它是一个很容易错过的实现细节时会出现问题。
如果可能的话,通常认为使用其他python功能实现相同的功能会更好的代码/更易于维护。
然而它可能很有用,std库中的namedtuple是使用~~ eval ~~ exec实现的(类似)。
其他人提到与goto的比较,这在某些方面也“太强大”,但可能非常有用(但仅限于c)。
我已经用它来为我的代码开发有用的调试函数和ruby,就像字符串插值一样。