Python'eval'对列表反序列化的安全性

2024-10-01 11:36:34 发布

您现在位置:Python中文网/ 问答频道 /正文

在这种情况下,是否存在任何安全漏洞:

eval(repr(unsanitized_user_input), {"__builtins__": None}, {"True":True, "False":False})

其中unsanitized_user_input是str对象。这个字符串是用户生成的,可能很讨厌。假设我们的web框架没有让我们失望,它是Python内置的一个真正诚实的str实例。在

如果这很危险,我们能对输入做些什么来保证它的安全吗?在

我们绝对不想执行字符串中包含的任何内容。在

另请参见:

更大的背景(我相信)对这个问题并不重要,那就是我们有数以千计的:

^{pr2}$

在某些情况下,嵌套:

repr([[unsanitized_user_input_1,
       unsanitized_user_input_2],
      [unsanitized_user_input_3,
       unsanitized_user_input_4],
       ...])

它们本身用repr()转换为字符串,放入持久存储器,最后用eval读回内存。在

Eval从持久存储中反序列化字符串的速度比pickle和simplejson快得多。json和ast都不可用。不允许使用C模块,也不允许使用cPickle。在


Tags: 对象字符串用户nonefalsetrueinputeval
3条回答

这确实很危险,最安全的替代方法是ast.literal_eval(请参阅标准库中的ast模块)。当然,您可以构建和修改ast,以便在计算结果AST之前提供变量的求值等(当它是文本时)。在

eval的可能攻击从它能得到它的任何对象开始(这里说True),然后经过.uu类到它的类型对象,等等,直到object,然后得到它的子类。。。基本上,它可以达到任何对象类型和破坏浩劫。我可以说得更具体一些,但我不想在公共论坛上这样做(这个漏洞是众所周知的,但是考虑到有多少人仍然忽视它,把它透露给想要脚本的孩子可能会让事情变得更糟。。。只需避免eval未经确认的用户输入,从此过上幸福的生活!-). 在

如果您可以毫无疑问地证明unsanitized_user_input是一个来自Python内置的str实例,那么这总是安全的。{3}实际上,所有这些对象都是安全的。你放了一根绳子,你就得到了一根绳子。你所做的就是逃走,把它找出来。在

这一切让我认为eval(repr(x))不是你想要的——除非有人给你一个看起来像字符串但不是字符串的unsanitized_user_input对象,否则不会执行任何代码,但这是另一个问题——除非你试图以最慢的方式复制字符串实例:D

正如您所描述的,从技术上讲,评估repred字符串是安全的,但是,无论如何我都会避免这样做,因为这会带来麻烦:

  • 可能会出现一些奇怪的情况,您假设只存储已重复的字符串(例如,错误/进入存储的不同路径不会立即报告,这会成为代码注入漏洞,否则可能无法利用)

  • 即使现在一切正常,假设也可能在某个时刻发生变化,未定义的数据可能会被不知道eval代码的人存储在该字段中。

  • <>你的代码可能会被重用(或者更糟,复制+粘贴)进入你没有考虑的情况。

正如Alex Martelli指出的,在python2.6及更高版本中,有ast.literal_评估它可以安全地处理字符串和其他简单的数据类型,如元组。这可能是最安全和最完整的解决方案。在

然而,另一种可能是使用string-escape编解码器。这比eval快得多(根据timeit,大约是eval的10倍),在早期版本中比literal_eval可用,并且应该执行您想要的操作:

>>> s = 'he\nllo\' wo"rld\0\x03\r\n\tabc'
>>> repr(s)[1:-1].decode('string-escape') == s
True

([1:-1]将去掉repr添加的外部引号。)

相关问题 更多 >