Python pickle 反序列化详解

本文详细介绍了Python的pickle库用于反序列化的功能,包括不同版本的协议,强调了pickle协议的向前兼容性。文章通过示例展示了如何使用pickle.dumps和pickle.loads进行对象的反序列化,并探讨了反序列化过程中的指令集,如MARK、APPENDS、REDUCE等。同时,文章还深入讨论了pickle反序列化可能存在的安全风险,如RCE漏洞,并通过`__reduce__`方法的利用进行讲解,展示了如何构造payload以达到执行特定命令的效果。
摘要由CSDN通过智能技术生成

什么是Python反序列化
python反序列化和php反序列化类似(还没接触过java。。),相当于把程序运行时产生的变量,字典,对象实例等变换成字符串形式存储起来,以便后续调用,恢复保存前的状态

python中反序列化的库主要有两个,pickle和cPickle,这俩除了运行效率上有区别外,其他没啥区别

pickle的常用方法有

import pickle

a_list = [‘a’,‘b’,‘c’]

pickle构造出的字符串,有很多个版本。在dumps或loads时,可以用Protocol参数指定协议版本,例如指定为0号版本

目前这些协议有0,2,3,4号版本,默认为3号版本。这所有版本中,0号版本是人类最可读的;之后的版本加入了一大堆不可打印字符,不过这些新加的东西都只是为了优化,本质上没有太大的改动。

一个好消息是,pickle协议是向前兼容的。0号版本的字符串可以直接交给pickle.loads(),不用担心引发什么意外。

pickle.dumps将对象反序列化为字符串

pickle.dump将反序列化后的字符串存储为文件

print(pickle.dumps(a_list,protocol=0))

pickle.loads() #对象反序列化
pickle.load() #对象反序列化,从文件中读取数据
输出反序列化在这里插入图片描述
在这里插入图片描述

读入反序列化

image-20210225122449100

可以看出,python2和python3之间反序列化的结果有些许差别,我们先以目前的支持版本python3为主要对象,在后期给出exp的时候再补上python2

python3大多版本中反序列化的字符串默认版本为3号版本,我这里python3.8的默认版本为4

v0 版协议是原始的 “人类可读” 协议,并且向后兼容早期版本的 Python。
v1 版协议是较早的二进制格式,它也与早期版本的 Python 兼容。
v2 版协议是在 Python 2.3 中引入的。它为存储 new-style class 提供了更高效的机制。欲了解有关第 2 版协议带来的改进,请参阅 PEP 307。
v3 版协议添加于 Python 3.0。它具有对 bytes 对象的显式支持,且无法被 Python 2.x 打开。这是目前默认使用的协议,也是在要求与其他 Python 3 版本兼容时的推荐协议。
v4 版协议添加于 Python 3.4。它支持存储非常大的对象,能存储更多种类的对象,还包括一些针对数据格式的优化。有关第 4 版协议带来改进的信息,请参阅 PEP 3154。
为了便于分析和兼容,我们统一使用3号版本

C:\Users\Rayi\Desktop\Tmp\Script
λ python 1.py
b’(lp0\nVa\np1\naVb\np2\naVc\np3\na.’ #0号
b’\x80\x03]q\x00(X\x01\x00\x00\x00aq\x01X\x01\x00\x00\x00bq\x02X\x01\x00\x00\x00cq\x03e.’ #3号
b’\x80\x04\x95\x11\x00\x00\x00\x00\x00\x00\x00]\x94(\x8c\x01a\x94\x8c\x01b\x94\x8c\x01c\x94e.’#4号
反序列化流程分析
在挖掘反序列化漏洞之前,我们需要了解python反序列化的流程是怎样的

直接分析反序列化出的字符串是比较困难的,我们可以使用pickletools帮助我们进行分析

import pickle
import pickletools

a_list = [‘a’,‘b’,‘c’]

a_list_pickle = pickle.dumps(a_list,protocol=0)
print(a_list_pickle)

优化一个已经被打包的字符串

a_list_pickle = pickletools.optimize(a_list_pickle)
print(a_list_pickle)

反汇编一个已经被打包的字符串

pickletools.dis(a_list_pickle)image-20210225135739565

指令集如下:(更具体的解析可以查看pickletools.py)

MARK = b’(’ # push special markobject on stack
STOP = b’.’ # every pickle ends with STOP
POP = b’0’ # discard topmost stack item
POP_MARK = b’1’ # discard stack top through topmost markobject
DUP = b’2’ # duplicate top stack item
FLOAT = b’F’ # push float object; decimal string argument
INT = b’I’ # push integer or bool; decimal string argument
BININT = b’J’ # push four-byte signed int
BININT1 = b’K’ # push 1-byte unsigned int
LONG = b’L’ # push long; decimal string argument
BININT2 = b’M’ # push 2-byte unsigned int
NONE = b’N’ # push None
PERSID = b’P’ # push persistent object; id is taken from string arg
BINPERSID = b’Q’ # " " " ; " " " " stack
REDUCE = b’R’ # apply callable to argtuple, both on stack
STRING = b’S’ # push string; NL-terminated string argument
BINSTRING = b’T’ # push string; counted binary string argument
SHORT_BINSTRING= b’U’ # " " ; " " " " < 256 bytes
UNICODE = b’V’ # push Unicode string; raw-unicode-escaped’d argument
BINUNICODE = b’X’ # " " " ; counted UTF-8 string argument
APPEND = b’a’ # append stack top to list below it
BUILD = b’b’ # call setstate or dict.update()
GLOBAL = b’c’ # push self.find_class(modname

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值