Python序列化和反序列化使用以及部分漏洞利用

最近研究了一下java和python的反序列化方面的漏洞,觉得很有意思,来做一个小小的总结,(PS:以前的博客停用了,现在在CSDN上继续更新,以前的文章会慢慢的搬过来)

一.序列化与反序列化

  • 序列化:把对象转换为字节序列的过程称为对象的序列化
  • 反序列化:把字节序列恢复为对象的过程称为对象的反序列化。
  • 用途:把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中,并且能在网络上传输对象的字节序列。
  • python中序列化通常有两种方式:pickle模块和json模块,这里我们主要讲一下pickle模块。

二.pickle模块使用

对于大多数应用程序来讲,dump()和load()函数的使用就是你使用pickle
模块所需的全部了。

函数

解释

dumps

将对象反序列化为bytes对象

dump

将对象反序列化到文件对象,存入文件

loads

对bytes对象进行反序列化

load

通过对象反序列化,从文件中读取数据

dump和load的使用如下:

import pickle
dict1 = {"c": 1, "l": 2, "e": 3}
b = pickle.dumps(dict1)
print(b,type(b)) # 序列化
c = pickle.loads(b)
print(c,type(c)) # 反序列化

结果:

b'\x80\x03}q\x00(X\x01\x00\x00\x00cq\x01K\x01X\x01\x00\x00\x00lq\x02K\x02X\x01\x00\x00\x00eq\x03K\x03u.' <class 'bytes'>
{'c': 1, 'l': 2, 'e': 3} <class 'dict'>

dumps和loads的使用如下:

import pickle
dict = {"c": 1, "l": 2, "e": 3}
file = open("clean.txt", "wb")
pickle.dump(dict, file)
file.close()
file = open("clean.txt", "rb")
result = pickle.load(file)
file.close()
print(id(dict), result, id(result))

结果:

2817625308360 {'c': 1, 'l': 2, 'e': 3} 2817625308440
#反序列化后的对象跟以前不一样了

三.pickle模块漏洞利用

关键在于__reduce__函数的使用,官方文档链接如下
https://docs.python.org/2/library/pickle.html#object.reduce 简单总结下:

  1. 如果返回值是一个字符串,那么将会去当前作用域中查找字符串值对应名字的对象,将其序列化之后返回,例如最后return('a'),那么它就会在当前的作用域中寻找名为a的对象然后返回,否则报错。
  2. 如果返回值是一个元组,要求是2到5个参数,第一个参数是可调用的对象,第二个是该对象所需的参数元组,剩下三个可选。所以比如最后return(eval,("os.system('ls')",)),那么就是执行eval函数,然后元组内的值作为参数,从而达到执行命令或代码的目的,当然也可以return(os.system,('ls',))
import pickle
import os
class clean(object):
    def __reduce__(self):
        #return (eval,("os.system('ls')",))
        return (os.system,('ls',))

a=clean()
b=pickle.dumps(a)
print(b)
pickle.loads(b)

四.结语

通过此次回顾序列方面的知识,使我对序列化和反序列化漏洞的构造有了更深的理解,也见识了php以外的其他语言的序列化构造,进入到忙录的考研生活中,对于安全的学习时间也在逐渐减少。但因为热爱,还是会抽出时间继续前行。(java可能会晚点发)

五.pickle模块漏洞涉及的CTF题目

[CISCN2019 华北赛区 Day1 Web2]ikun
考点:主要考察JWT,pickle的知识点,难度适中。WP以前写过这里就不写了,百度上搜一下应该都能搜到。