जमा करें #955441: BerriAI LiteLLM Proxy 1.82.1 - 1.92.0 Access Control / IDORजानकारी

शीर्षकBerriAI LiteLLM Proxy 1.82.1 - 1.92.0 Access Control / IDOR
विवरणBerriAI LiteLLM Proxy Server contains a Missing Authorization / Insecure Direct Object Reference (IDOR) vulnerability in the endpoint GET /spend/logs/session/ui, implemented in litellm/proxy/spend_tracking/spend_management_endpoints.py (function ui_view_session_spend_logs). The handler authenticates the caller via Depends(user_api_key_auth) but queries spend logs filtered only by the session_id query parameter, without constraining results to the caller's own user_id, team_id, or organization_id. ROOT CAUSE Source: spend_management_endpoints.py:3251 (session_id read from query string), user_api_key_dict at :3266 (used only for auth, never for filtering). Sink: :3290 where_conditions = {"session_id": session_id}, raw SQL at :3309 "WHERE session_id = $1". Returned columns include api_key, "user", team_id, organization_id, model, spend, requester_ip_address, session_id (:3300-3307). Reachability: /spend/logs/session/ui is in spend_tracking_routes (_types.py:628), included in internal_user_routes (_types.py:724), so RouteChecks admits any INTERNAL_USER role, not just admins. This contradicts the proxy's own documented intent (_types.py:701: "non-admin roles must not see other tenants' spend") and is inconsistent with sibling endpoints that scope correctly: /spend/logs/v2 filters non-admins via where_conditions["user"] = user_api_key_dict.user_id (:1847,1862), and per-request-id access is gated by _assert_user_can_view_request_id (:3555). The session endpoint, added in commit 331e784db4 (PR #10321, first released in v1.82.1), omits the equivalent check. PROOF OF CONCEPT (step by step, curl only) Setup: two separate non-admin internal_user accounts on the same proxy, Alice (victim) and Bob (attacker), each with their own virtual API key, created via POST /user/new + POST /key/generate using the proxy master key. Step 1 - Alice generates activity tagged with a session id: curl -s $PROXY/v1/chat/completions \ -H "Authorization: Bearer $ALICE_KEY" -H "Content-Type: application/json" \ -d '{"model":"mock-gpt","messages":[{"role":"user","content":"alice private"}],"litellm_session_id":"alice-secret-session-21849"}' -> HTTP 200. This is a normal, legitimate request; the session_id is just a tag LiteLLM uses to group related calls. Step 2 - Bob, an unrelated non-admin user with no relationship to Alice, queries the session endpoint using Alice's session_id (session_id values may leak to other users via shared UI views, logs, referrers, screenshots, or tickets - they are not secret by design): curl -s "$PROXY/spend/logs/session/ui?session_id=alice-secret-session-21849" \ -H "Authorization: Bearer $BOB_KEY" Result: HTTP 200 with 1 record, containing Alice's full spend row: api_key = 8546673c9754991a0277c50e8a5c1da9d1b9cf5424a42ee33037ddd1984f4074 (hashed key) user = 7265de41-f98a-4e2f-8bdc-e1f102a52145 (Alice's user_id) model = openai/gpt-4o spend = 0.000225 session_id = alice-secret-session-21849 requester_ip_address = 172.18.0.1 Bob's own key has no admin role and no team/org relationship to Alice; he authenticates only as himself, yet receives Alice's tenant data in full. Step 3 - Control, showing the boundary IS enforced elsewhere (confirms this endpoint is the outlier, not general proxy behavior): curl -s -o /dev/null -w "%{http_code}" "$PROXY/user/info?user_id=$ALICE_USER_ID" -H "Authorization: Bearer $BOB_KEY" -> HTTP 403 (correctly denied) A complete runnable script reproducing steps 1-3 end to end (auto-provisions both test users, retries for async log flush, dumps the full cross-tenant JSON) plus a screen recording of the live run are available on request / in the referenced advisory. IMPACT Any authenticated non-admin user who learns another tenant's session_id can retrieve that tenant's hashed API key, user_id, team_id, organization_id, model usage, spend, and requester IP address, without any authorization relationship to the victim. AFFECTED VERSIONS v1.82.1 through v1.92.0 (latest stable, confirmed unscoped) and the 1.93.0-dev/1.94.0-dev line (commit f1f33f560f, live-tested). No fix available as of the tested commit. FIX Scope the query to the caller for non-admin roles before returning results, mirroring /spend/logs/v2 and _assert_user_can_view_request_id: add a check that the caller's user_id/team_id/org_id matches the session's owner, or filter the query itself (e.g. AND "user" = $n). Admins retain full visibility via the existing global routes. CWE-639 (Authorization Bypass Through User-Controlled Key), CWE-862 (Missing Authorization). CVSS 3.1: AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N (4.3, Medium).
स्रोत⚠️ https://github.com/BerriAI/litellm
उपयोगकर्ता
 Gabriel Alves (UID 99209)
सबमिशन01/09/2026 05:08 PM (1 महीना पहले)
संयम10/10/2026 05:37 PM (1 month later)
स्थितिस्वीकृत
VulDB प्रविष्टि416231 [BerriAI LiteLLM तक 1.95.0 Spend Tracking spend_management_endpoints.py ui_view_session_spend_logs session_id अधिकार वृद्धि]
अंक20

Do you know our Splunk app?

Download it now for free!