CVE-2026-42945 पर पूर्ण शोध रिपॉजिटरी जिसमें हीप बफर ओवरफ्लो विश्लेषण, RCE एक्सप्लॉइट (हीप स्प्रे + फेंग शुई), डिटेक्शन स्क्रिप्ट्स, और NGINX रीराइट मॉड्यूल कमजोरी के लिए पैचिंग मार्गदर्शन शामिल है।
NGINX ngx_http_rewrite_module में हीप बफर ओवरफ़्लो
| मीट्रिक | मान |
|---|---|
| CVSS v4.0 | 9.2 (क्रिटिकल) |
| CVSS v3.1 | 8.1 (उच्च) — AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H |
| CWE | 122 — हीप-आधारित बफर ओवरफ़्लो |
| शुरुआत | जून 2008 — v0.6.27 |
| खोज | अप्रैल 2026 — DepthFirst रिसर्च |
| फिक्स | 13 मई 2026 — v1.30.1, v1.31.0 |
| CVE प्रकाशित | 21 मई 2026 |
| जीवनकाल | ~18 वर्ष (अज्ञात) |
| फिक्स कमिट | 524977e7c534e87e5b55739fa74601c9f1102686 |
एक अप्रमाणित, दूरस्थ हमलावर एक विशिष्ट rewrite + set/if/rewrite कॉन्फ़िगरेशन पैटर्न वाले सर्वर पर एक क्राफ्टेड HTTP अनुरोध भेजकर NGINX वर्कर प्रक्रियाओं में एक निर्धारिती हीप बफर ओवरफ़्लो को ट्रिगर कर सकता है। यह ओवरफ़्लो हीप मेटाडेटा (ngx_pool_cleanup_t पॉइंटर्स) को दूषित करता है, जो हीप स्प्रे और फेंग शुई तकनीकों के माध्यम से रिमोट कोड निष्पादन (RCE) को सक्षम करता है।
server { listen 19321;
location ~ ^/api/(.*)$ {
rewrite ^/api/(.*)$ /internal?migrated=true;
set $original_endpoint $1;
}
}
**मुख्य आवश्यकताएँ:**
- एक `rewrite` निर्देश जिसके प्रतिस्थापन में `?` (क्वेरी-स्ट्रिंग विभाजक) हो
- एक बाद का `set`, `if`, या `rewrite` निर्देश जो एक **अनामित PCRE कैप्चर** (`$1`, `$2`, आदि) को संदर्भित करता है
- rewrite प्रतिस्थापन में `?` `ngx_http_script_start_args_code` को ट्रिगर करता है जो `e->is_args = 1` सेट करता है
### एक हमलावर क्या प्राप्त कर सकता है
| क्षमता | विवरण |
|-----------|-------------|
| **सेवा अस्वीकार (DoS)** | वर्कर प्रक्रियाओं को निर्धारित रूप से क्रैश करें, जिससे रीस्पॉन लूप उत्पन्न होते हैं (ASLR के बावजूद काम करता है) |
| **दूरस्थ कोड निष्पादन (RCE)** | ASLR अक्षम होने पर (या आंशिक ओवरराइट के माध्यम से बाईपास), nginx उपयोगकर्ता के रूप में पूर्ण RCE प्राप्त करें |
| **डेटा चोरी** | मेमोरी रीड प्रिमिटिव के माध्यम से, वर्कर हीप से संवेदनशील डेटा निकालें |
| **स्थायित्व** | वर्कर प्रक्रिया मेमोरी में कोड निष्पादन के माध्यम से बैकडोर लगाएं |
---
## 2. मूल कारण विश्लेषण
### दो-पास स्क्रिप्ट इंजन
NGINX का `ngx_http_rewrite_module` `src/http/ngx_http_script.c` में **दो-पास स्क्रिप्ट इंजन** का उपयोग करता है:
1. **लंबाई पास** (`ngx_http_script_run`): आवश्यक कुल बफर आकार की गणना करने के लिए सभी स्क्रिप्ट कोड पर पुनरावृत्ति करता है। `le.ip` और `le.pos` में लंबाई लिखता है।
2. **कॉपी पास** (`ngx_http_script_copy_len`/`_code`): फिर से पुनरावृत्ति करता है, पूर्व-आवंटित बफर में `e->ip` और `e->pos` पर वास्तविक बाइट्स लिखता है।
प्रत्येक स्क्रिप्ट कोड के लिए दो हैंडलर होते हैं: प्रत्येक पास के लिए एक। उदाहरण के लिए:
- `ngx_http_script_copy_len` → `ngx_http_script_copy_code`
- `ngx_http_script_start_args_len` → `ngx_http_script_start_args_code`
### `is_args` फ़्लैग
**इंजन संरचना** (`ngx_http_script_engine_t`) पर फ़्लैग `e->is_args` नियंत्रित करता है कि कॉपी पास कुछ वर्णों को कैसे संभालता है:```c
typedef struct {
u_char *ip;
u_char *pos;
ngx_http_variable_value_t *sp;
ngx_str_t buf;
int flushed;
unsigned is_args:1; // <-- THE BUG
unsigned ncaptures:1;
ngx_uint_t captures_size;
// ...
} ngx_http_script_engine_t;
जब e->is_args = 1, तो $N कैप्चर रेफरेंस के लिए कॉपी-कोड ngx_escape_uri() को NGX_ESCAPE_ARGS के साथ कॉल करता है, जो विस्तारित करता है:
+ → %2B (1 बाइट → 3 बाइट, +200%)% → %25 (1 बाइट → 3 बाइट, +200%)& → %26 (1 बाइट → 3 बाइट, +200%)असुरक्षित पैटर्न के लिए निष्पादन प्रवाह:``` rewrite ^/api/(.*)$ /internal?migrated=true;
1. **पुनर्लेखन मूल्यांकन** के दौरान, इंजन प्रतिस्थापन स्ट्रिंग में `?` का सामना करता है, जो `ngx_http_script_start_args_code` को सक्रिय करता है, जिससे `e->is_args = 1` सेट होता है।
2. पुनर्लेखन अनुरोध URI को संशोधित करता है और फिर अगले निर्देश पर जारी रहता है।
3. **`e->is_args` कभी साफ़ नहीं किया जाता**।
फिर:```
set $original_endpoint $1;
le) लंबाई पास के लिए बनाया गया है: ```c
ngx_memzero(&le, sizeof(ngx_http_script_engine_t));
यह सही रूप से le.is_args = 0 को शून्य कर देता है, जिससे लंबाई पास कच्ची, अनएस्केप्ड कैप्चर लंबाई लौटाती है।
e का पुन: उपयोग करता है, जिसमें चरण 1 से अभी भी e->is_args = 1 है। कॉपी पास URI-एस्केपिंग लागू करता है, प्रत्येक एस्केप करने योग्य वर्ण को 1 बाइट से 3 बाइट्स में विस्तारित करता है, जो एक बफर के अंदर होता है जिसका आकार कच्ची लंबाई के लिए निर्धारित किया गया था — हीप ओवरफ़्लो।Pass 1 (Length — sub-engine le): le.is_args = 0 capture $1 = "A+++++B" → length = 7
Buffer allocated: 7 bytes
Pass 2 (Copy — main engine e): e.is_args = 1 ← LEAKED from rewrite capture $1 = "A+++++B" ngx_escape_uri("A+++++B", NGX_ESCAPE_ARGS): A → A (1 byte) + → %2B (3 bytes) ← EXPANSION + → %2B (3 bytes) + → %2B (3 bytes) + → %2B (3 bytes) + → %2B (3 bytes) B → B (1 byte) total written: 17 bytes buffer size: 7 bytes OVERFLOW: 10 bytes
विस्तार अनुपात `7 + (n_escapable * 2)` है, जहाँ `n_escapable` कैप्चर में `+`, `%` और `&` की संख्या है।
---
## 3. शोषण यांत्रिकी
### अवलोकन
| चरण | तकनीक | विवरण |
|------|-----------|-------------|
| 1 | ओवरफ्लो | हीप बफर को ओवरफ्लो करने के लिए `+` पैडिंग के साथ तैयार URI भेजें |
| 2 | हीप स्प्रे | नियंत्रित डेटा से हीप भरने के लिए `/spray` पर बड़े बॉडी वाले POST भेजें |
| 3 | फेंग शुई | आवंटन को इस प्रकार व्यवस्थित करें कि ओवरफ्लो लक्ष्य (`ngx_pool_cleanup_t`) सन्निकट हो |
| 4 | हैंडलर दूषित करें | ओवरफ्लो `ngx_pool_cleanup_t.handler` को `system()` पते से अधिलेखित कर देता है |
| 5 | क्लीनअप ट्रिगर करें | पूल विनाश की प्रतीक्षा करें → `system(cmd)` हमलावर के कमांड को निष्पादित करता है |
| 6 | रिवर्स शेल | इंटरैक्टिव पहुँच के लिए रिवर्स शेल पेलोड से जुड़ें |
### क्रॉस-अनुरोध फेंग शुई
**एकल-अनुरोध फेंग शुई विफल होता है** क्योंकि ओवरफ्लो `cleanup` पॉइंटर तक पहुँचने से पहले पूल के मेटाडेटा (`->d.next`, `->d.failed`) को दूषित कर देता है। जब अनुरोध के अंत में पूल नष्ट होता है, तो दूषित मेटाडेटा `system()` को कॉल किए जाने से पहले **क्रैश** का कारण बनता है।
इसके बजाय, शोषण **क्रॉस-अनुरोध फेंग शुई** का उपयोग करता है:
1. **अनुरोध 1 (स्प्रे)**: `/spray` पर बड़े बॉडी के साथ POST करें। बैकएंड (`server.py`) `X-Delay` हेडर के साथ प्रतिक्रिया रोकता है, कनेक्शन खुला रखता है और हीप आवंटन को संरक्षित करता है। स्प्रे हीप को नकली `ngx_pool_cleanup_t` ब्लॉक से भरता है।
2. **अनुरोध 2 (ओवरफ्लो)**: ओवरफ्लो URI भेजें। ओवरफ्लो केवल `cleanup` पॉइंटर (पूल मेटाडेटा नहीं) को दूषित करता है, इसे स्प्रे किए गए नकली ब्लॉक की ओर इंगित करता है।
3. **पूल विनाश**: जब स्प्रे प्रतिक्रिया पूरी होती है (विलंब समाप्त), तो पूल की क्लीनअप श्रृंखला नकली ब्लॉक पर जाती है और `system(cmd)` को कॉल करती है।
### पता आवश्यकताएँ