
यह दस्तावेज़ CVE-2025-55182 में मेरी व्यक्तिगत शोध प्रक्रिया का वर्णन करता है, जिसमें पुष्टि किए गए निष्कर्ष और मेरे द्वारा किए गए प्रयोग शामिल हैं। यह मेरी जाँच का एक ईमानदार विवरण है, जिसमें प्रारंभिक गलत धारणाएँ और अंतिम सफलता दोनों शामिल हैं।
CVE-2025-55182 (CVSS 10.0) में व्यापक जाँच के बाद, मेरा प्रारंभिक निष्कर्ष यह था कि स्वचालित RCE का सार्वजनिक रूप से प्रदर्शन नहीं किया गया था और शोषण के लिए एप्लिकेशन-विशिष्ट gadgets की आवश्यकता होती थी। यह निष्कर्ष गलत था।
5 दिसंबर 2025 को, X पर एक अन्य स्वतंत्र शोधकर्ता (@maple3142) से अतिरिक्त जानकारी प्राप्त करने के बाद, मैंने बिना किसी एप्लिकेशन-विशिष्ट कोड भेद्यता की आवश्यकता के, सादे (vanilla) Next.js पर पूर्ण unauthenticated RCE सफलतापूर्वक दोहराया।
मेरा प्रारंभिक ध्यान React 19.0.1 पैच में पहले बदलाव पर था:
कमजोर (19.0.0):
return fn.bind.apply(fn, [null].concat(_ref));
पैच किया गया (19.0.1):
if (Array.isArray(promiseValue)) {
promiseValue = promiseValue.slice(0);
} else {
promiseValue = [];
}
मैंने मान लिया कि हमले का रास्ता arrays के बजाय दुर्भावनापूर्ण objects के साथ fn.bind.apply() के माध्यम से था। मैं $ACTION_REF_ और attacker-नियंत्रित bound का उपयोग करके Server Actions में argument injection प्रदर्शित करने में सक्षम था:
curl -X POST http://localhost:9000/ \
-F '$ACTION_REF_0=' \
-F '$ACTION_0:0={"id":"<ACTION_ID>","bound":["; id #","/etc/passwd"]}'
परिणाम: Arguments सफलतापूर्वक Server Action में इंजेक्ट कर दिए गए। हालाँकि, यह केवल तभी RCE की ओर ले जाता है जब लक्षित फ़ंक्शन उन arguments का असुरक्षित रूप से उपयोग करता है।
पैच पर गहराई से नज़र डालने से getOutlinedModel() में एक और महत्वपूर्ण बदलाव सामने आया:
कमजोर:
for (key = 1; key < reference.length; key++)
parentObject = parentObject[reference[key]];
पैच किया गया:
if (hasOwnProperty.call(value, name)) {
value = value[name];
}
इस कमजोर व्यवहार ने निम्न जैसे references का उपयोग करके prototype-chain traversal की अनुमति दी:
$1:__proto__:constructor:constructor
शोध के दौरान, मैंने एक thenable object का परीक्षण किया जिसमें .then property थी:
{"then": "$1:__proto__:constructor:constructor"}
जब JavaScript इसे await के माध्यम से संसाधित करता है:
.then property देखता है और object को Promise के रूप में मानता हैobj.then(resolve, reject) को कॉल करता हैthen का समाधान Function.constructor से होता है, तो JavaScript Function(resolve, reject) को निष्पादित करने का प्रयास करता हैदेखा गया परिणाम:
SyntaxError: Unexpected token 'function'
at Object.Function [as then] (<anonymous>)
जब Function.constructor को निम्न रूप में बुलाया जाता है:
Function(resolve, reject)
// resolve.toString() = "function () { [native code] }"
// Function इस कोड को पार्स करने का प्रयास करता है → SyntaxError
Arguments resolve और reject हमेशा मूल native Promise functions होते हैं। Function पहले argument को source code के रूप में व्याख्या करने का प्रयास करता है, जो अमान्य JavaScript है।
यहीं पर मेरा शोध रुक गया। मैंने निष्कर्ष निकाला कि एप्लिकेशन-विशिष्ट gadget के बिना Function.constructor के arguments को नियंत्रित करना असंभव था।
अपने प्रारंभिक निष्कर्षों को प्रकाशित करने के बाद, एक अन्य स्वतंत्र शोधकर्ता ने मुझे उस महत्वपूर्ण टुकड़े की ओर इंगित किया जिसे मैं चूक गया था: $B (Blob) deserialization sink।
संकलित React Flight server code में (TypeScript स्रोतों में दिखाई नहीं देता), निम्न मौजूद है:
case "B":
return response._formData.get(response._prefix + id);
स्थान:
[email protected]cjs/react-server-dom-webpack-server.node.unbundled.development.js[email protected]/dist/compiled/react-server-dom-webpack/यह कोड React को attacker-नियंत्रित इनपुट से प्राप्त मानों के साथ response._formData.get() कॉल करने की अनुमति देता है, बिना किसी सत्यापन के।
| दृष्टिकोण | Function.constructor के Arguments | परिणाम |
|---|---|---|
| Thenable (चरण 3) | resolve, reject (native functions) | ❌ SyntaxError |
| Blob + Poisoned Response | _prefix (attacker-नियंत्रित स्ट्रिंग) | ✅ RCE |
निम्न को संयोजित करके:
$1:__proto__:then → Chunk.prototype.then)_response object जिसमें:
_formData.get को Function.constructor पर सेट किया गया_prefix को मनमाना JavaScript कोड पर सेट किया गया$B reference शामिल हैcase "B": handler निष्पादित करता है:
Function.constructor("<attacker कोड>" + id)
यह argument binding सीमा को पूरी तरह से बायपास कर देता है।
RCE का दावा करने वाले लोकप्रिय GitHub PoCs निम्न Action IDs का उपयोग करते हैं:
"child_process#execSync""vm#runInThisContext"ये नकली हैं। Next.js केवल एप्लिकेशन द्वारा परिभाषित Action IDs को स्वीकार करता है। अमान्य IDs निम्न उत्पन्न करती हैं:
TypeError: Cannot read properties of undefined (reading 'workers')
हालाँकि, वास्तविक exploit के लिए नकली Action IDs की आवश्यकता नहीं होती। कोई भी मान्य Server Action ID काम करती है।
मैंने इस exploitation श्रृंखला का परीक्षण एक न्यूनतम Next.js 15.0.3 + React 19.0.0 एप्लिकेशन पर केवल निम्न के साथ किया:
async function myAction(data) {
"use server";
console.log("Server Action called with:", data);
return { success: true, received: data };
}
परिणाम: पूर्ण RCE की पुष्टि हुई। एप्लिकेशन में कोई असुरक्षित कोड, कोई eval, कोई execSync, कोई gadgets नहीं थे।
5 दिसंबर 2025 तक, $B sink अभी भी Next.js 15.0.5 (कथित रूप से पैच किया गया संस्करण) में मौजूद है।
सत्यापन:
$ npm pack [email protected]
$ tar -xzf next-15.0.5.tgz
$ grep -A5 'case "B":' package/dist/compiled/react-server-dom-webpack/cjs/react-server-dom-webpack-server.node.development.js
परिणाम:
case "B":
return response._formData.get(response._prefix + obj);
कोड कमजोर संस्करण के समान है।
इस खोज के कारण कि भेद्यता "ठीक" किए गए दावे वाले संस्करणों में पूरी तरह से पैच नहीं की गई हो सकती है, मैं Vercel और Meta की सुरक्षा टीमों के साथ सत्यापन होने तक पूर्ण proof-of-concept payload को रोक रहा हूँ।
इस दस्तावेज़ में दिए गए तकनीकी विवरण भेद्यता तंत्र को समझने के लिए पर्याप्त हैं लेकिन तत्काल शोषण को रोकने के लिए जानबूझकर अपूर्ण हैं।
| तकनीक | स्थिति |
|---|---|
bound के माध्यम से Argument injection | ✅ पुष्टि (सीमित प्रभाव) |
| Prototype traversal |
| मुद्दा | प्रभाव |
|---|---|
$B (Blob) deserialization sink | ❌ महत्वपूर्ण - argument नियंत्रण सक्षम करता है |
| संकलित बनाम स्रोत कोड की जाँच | ❌ sink केवल संकलित आउटपुट में मौजूद है |
| Response object poisoning तंत्र | ❌ सभी सुरक्षाओं को बायपास करने की अनुमति देता है |
CVE-2025-55182 सादे (vanilla) Next.js एप्लिकेशन पर पूर्ण unauthenticated RCE के लिए exploitable है।
$B deserialization के बारे में जानकारी प्राप्त हुई$B deserialization अभी भी मनमाने _response objects स्वीकार करता हैNext-Action headers$@, __proto__, $B पैटर्न वाले जटिल multipart payloads$B deserialization के संबंध में सफलता की जानकारी X पर एक शोधकर्ता (@maple3142) द्वारा प्रदान की गईअंतिम अद्यतन: 5 दिसंबर 2025
| पहलू | निष्कर्ष |
|---|
| प्रमाणीकरण आवश्यक? | ❌ नहीं |
| एप्लिकेशन gadget आवश्यक? | ❌ नहीं |
| सादे (vanilla) Next.js पर काम करता है? | ✅ हाँ |
| आवश्यक अनुरोधों की संख्या | 1 POST |
| प्रभावित संस्करण | Next.js ≤15.0.4 + React 19.0.0 |
| CVSS स्कोर | 10.0 (उचित) |
| ✅ पुष्टि |
Thenable के माध्यम से Function.constructor तक पहुँच | ✅ पुष्टि (लेकिन अकेले exploitable नहीं) |
| कमजोर संस्करणों का पता लगाना | ✅ पुष्टि |