
CVE-2026-42533: map/script इंजन में PCRE कैप्चर क्लोबरिंग से nginx का pre-auth हीप ओवरफ़्लो और जानकारी लीक, जो RCE तक चेन किया जाता है।
nginx में प्री-ऑथ हीप बफर ओवरफ़्लो और हीप सूचना लीक, जो स्क्रिप्ट इंजन के दो पासों के बीच PCRE कैप्चर स्टेट के सेव/रेस्टोर न होने के कारण होता है। दो कैप्चर संदर्भों के बीच मूल्यांकित एक regex map वेरिएबल r->captures को अधिलेखित कर देता है, जिससे LEN पास और VALUE पास इस बात पर असहमत हो जाते हैं कि एक कैप्चर कितना बड़ा है। बफर एक कैप्चर के आकार का होता है और दूसरे से भर दिया जाता है। बड़ा क्लोबर हमलावर-नियंत्रित सामग्री और लंबाई के साथ हीप ओवरफ़्लो देता है। छोटा क्लोबर एक अत्यधिक बड़ा बफर देता है जिसकी अप्रारंभित पूँछ क्लाइंट को लौटा दी जाती है, जिससे libc और हीप पॉइंटर लीक हो जाते हैं।
दोनों प्रिमिटिव मिलकर विश्वसनीय प्री-ऑथ रिमोट कोड एक्ज़ीक्यूशन श्रृंखला बनाते हैं। लीक एक ही GET में ASLR को पराजित कर देता है, इसलिए ओवरफ़्लो के लिए ASLR को अक्षम करने की आवश्यकता नहीं होती।
विवरण: https://cyberstan.co.uk/nginx-rce/ परामर्श: F5 K000162097 रिपोर्टकर्ता: Stan Shaw (cyberstan)
nginx 0.9.6 से 1.30.3 (स्टेबल) और 1.31.2 (मेनलाइन), 2011 में map डायरेक्टिव को regex समर्थन मिलने के बाद से पहुँच योग्य। http और stream दोनों मॉड्यूल प्रभावित हैं। 13 कॉल साइटों पर लगभग 50 डायरेक्टिव, साथ ही नामित कैप्चर (r->variables[]) के माध्यम से दूसरा पथ। 1.30.4 और 1.31.3 में सुधार किया गया।
CVE-2026-42533-PoC/
├── exploits/ exploit and validator scripts
│ ├── poc.py numbered-capture proxy_method chain (crash/leak/rce/rce-det)
│ ├── calibrate.py find PL_OFF / HEAP_PAGE_OFF for --rce-det on your build
│ ├── leak_multi.py info leak on the return and set sinks
│ ├── test_all_sites.py ASan validator, all 13 overflow sites
│ └── named_capture_poc.py named-capture r->variables[] variant
├── configs/ nginx configs the exploits run against
│ ├── nginx_poc.conf crash / leak / rce
│ └── nginx_det.conf deterministic rce-det
├── docs/
│ └── EXPLOITATION.md full exploitation writeup
└── README.md
रिपॉज़िटरी रूट से नीचे दिए गए हर कमांड को चलाएँ, ताकि exploits/, configs/ और ../nginx-1.30.1 बिल्ड ट्री सभी सही ढंग से रिज़ॉल्व हों।
exploits/poc.py मुख्य एक्सप्लॉइट है (नंबरित कैप्चर, proxy_method सिंक)। इसके मोड:
बग की शेष सतह को कवर करने वाली स्टैंडअलोन स्क्रिप्ट:
कॉन्फ़िग configs/ में हैं: nginx_poc.conf (crash/leak/rce), nginx_det.conf (rce-det)। पूरा विवरण docs/EXPLOITATION.md में है।
Linux, gcc, python3, और nginx 1.30.1 सोर्स। Ubuntu 24.04.4, glibc 2.39, PCRE2 10.42, python 3.12, पूर्ण ASLR पर विकसित और परीक्षित।
दो बिल्ड। लीक और RCE के लिए एक क्लीन बिल्ड, ताकि हीप अवशेष वास्तविक रहे। क्रैश और साइट वैलिडेटरों के लिए एक AddressSanitizer बिल्ड, ताकि ओवरफ़्लो की सूचना सटीक राइट साइज़ और स्टैक के साथ मिले।
tar xf nginx-1.30.1.tar.gz
cd nginx-1.30.1
# clean build -> objs.dbg/nginx (leak, rce)
./configure --with-pcre --with-http_ssl_module --with-debug --builddir=objs.dbg
make -j"$(nproc)"
# ASan build with all the modules the site validator needs -> objs/nginx
./configure --with-pcre --with-http_ssl_module --with-http_v2_module \
--with-stream --with-stream_ssl_preread_module --with-stream_ssl_module \
--with-debug \
--with-cc-opt='-g -O0 -fsanitize=address -fno-omit-frame-pointer' \
--with-ld-opt=-fsanitize=address --builddir=objs
make -j"$(nproc)"
exploits/poc.py 127.0.0.1:8950 पर चल रहे nginx से संवाद करता है। इसे एक टर्मिनल में configs/nginx_poc.conf के साथ शुरू करें, फिर दूसरे टर्मिनल में अपना इच्छित मोड चलाएँ। बाकी तीन स्क्रिप्ट अपना nginx स्वयं शुरू और बंद करती हैं, इसलिए उन्हें केवल NGINX_BIN की आवश्यकता होती है।
mkdir -p run/logs
../nginx-1.30.1/objs/nginx -p run -c "$PWD/configs/nginx_poc.conf" # ASan build, foreground
python3 exploits/poc.py --crash
अपेक्षित परिणाम: एक हीप-बफर-ओवरफ़्लो, ngx_http_script.c:1404 पर ngx_http_script_copy_capture_code में WRITE of size 200, जिसे ngx_http_proxy_create_request में ngx_http_complex_value से कॉल किया गया है।
../nginx-1.30.1/objs.dbg/nginx -p run -c "$PWD/configs/nginx_poc.conf" # clean build
python3 exploits/poc.py --leak
अपेक्षित परिणाम: 8161 बाइट का बॉडी, जिसमें 2 बाइट लिखे गए हैं और शेष हीप अवशेष है। ऑफ़सेट 0x08 पर एक libc पॉइंटर और 0x10 पर एक हीप पॉइंटर।
../nginx-1.30.1/objs.dbg/nginx -p run -c "$PWD/configs/nginx_poc.conf" # clean build
python3 exploits/poc.py --rce # writes /tmp/PWNED via system()
अपेक्षित परिणाम: एक लीक, लगभग 40 स्प्रे कनेक्शन, एक ओवरफ़्लो ट्रिगर, फिर id का आउटपुट रखने वाला /tmp/PWNED। यह सिंगल शॉट है और डेव बिल्ड पर लगभग दो-तिहाई बार सफल होता है; चूक जाने पर वर्कर क्रैश हो जाता है और आप इसे दोबारा चलाते हैं। docs/EXPLOITATION.md का "Reliability" अनुभाग देखें।
नियंत्रित कॉन्फ़िग के विरुद्ध यही बग एक डिटर्मिनिस्टिक सिंगल शॉट है। यह लीक से एक पंक्ति में पूर्ण हीप बेस प्राप्त करता है (heap_base = (leaked_ptr & ~0xfff) - 0x22000), एक होल्ड किए गए कनेक्शन में ज्ञात पते पर एक एकल जाली पूल क्लीनअप रखता है, और पीड़ित पूल के क्लीनअप को क्षणिक ट्रिगर बॉडी के बजाय उसकी ओर इंगित करता है, जिसे nginx टियरडाउन से पहले मुक्त कर देता है।
mkdir -p run/logs
../nginx-1.30.1/objs.dbg/nginx -p run -c "$PWD/configs/nginx_det.conf" # controlled config
python3 exploits/poc.py --rce-det
nginx_det.conf एक प्रयोगशाला कॉन्फ़िग है (एकल वर्कर, निश्चित बफर) जिसका हीप लेआउट पुनरुत्पादनीय है, जिससे poc.py में दिए ऑफ़सेट (PL_OFF, HEAP_PAGE_OFF) मान्य रहते हैं। PL_OFF हीप बेस से वह ऑफ़सेट है जिस पर होल्ड किया गया POST /b/ क्लीनअप बॉडी स्थित होता है; यह सटीक आवंटन अनुक्रम पर निर्भर करता है, इसलिए यह बिल्ड, glibc संस्करण और कॉन्फ़िग के अनुसार बदलता है। यदि --rce-det Recalibrate की सूचना दे, तो calibrate.py से चालू वर्कर पर सही मान पढ़ें:
NGINX_BIN=../nginx-1.30.1/objs.dbg/nginx python3 exploits/calibrate.py
# prints e.g. set PL_OFF = 0x14426 , then edit it in exploits/poc.py
एकमात्र अन्य गैर-सफल स्थिति एक ASLR ड्रॉ है जो क्लीनअप पते या ओवरफ़्लो बॉडी के अंदर 0x0a डाल देता है, जिसे map regex के माध्यम से नहीं भेजा जा सकता; टूल इसकी सूचना देता है और आप दोबारा चलाते हैं। एक स्टॉक तैनाती इतनी पूर्वानुमेय नहीं होती, इसलिए वहाँ --rce का उपयोग करें। docs/EXPLOITATION.md में "A deterministic build" देखें।
NGINX_BIN=../nginx-1.30.1/objs/nginx python3 exploits/test_all_sites.py # ASan build
NGINX_BIN=../nginx-1.30.1/objs/nginx python3 exploits/test_all_sites.py 1 7 12 # a subset
NGINX_BIN=../nginx-1.30.1/objs/nginx python3 exploits/named_capture_poc.py # ASan build
NGINX_BIN=../nginx-1.30.1/objs.dbg/nginx python3 exploits/leak_multi.py # clean build
अपेक्षित परिणाम: return और set प्रत्येक एक libc और एक हीप पॉइंटर लीक करते हैं, दोनों की पुष्टि वर्कर के /proc/<pid>/maps के विरुद्ध होती है।
दो चीज़ें लोगों को सबसे अधिक परेशान करती हैं: गलत बिल्ड (ASan बनाम क्लीन) का उपयोग, और आपके सेटअप से मेल न खाते --rce-det ऑफ़सेट। दोनों नीचे कवर किए गए हैं।
--rce लीक से रनटाइम पर libc बेस और एक हीप पॉइंटर प्राप्त करता है, इसलिए यह कोई पता हार्डकोड नहीं करता। हालाँकि, यह उन ऑफ़सेटों को हार्डकोड करता है जो उस बिल्ड और libc के लिए विशिष्ट हैं जिन पर इसे विकसित किया गया था:
LIBC_LEAK_OFFSET libc base to the leaked arena pointer
SYSTEM_OFFSET libc base to system()
BODY_DELTA_* leaked heap pointer to the overflow body buffer
POOL_OFF_FROM_BUF, D_LAST_OFF, D_END_OFF, LOG_OFF forged pool geometry
किसी भिन्न डिस्ट्रो, glibc या nginx बिल्ड पर इन्हें पुनः अंशांकित करने की आवश्यकता होती है। वास्तविक system() ऑफ़सेट readelf -sW /lib/x86_64-linux-gnu/libc.so.6 | grep '\bsystem\b' से पढ़ें, और पूल ऑफ़सेट लक्ष्य के ngx_pool_t से पढ़ें। --crash और --leak मोड में ऐसे कोई ऑफ़सेट नहीं होते और ये प्रभावित संस्करण के किसी भी बिल्ड पर पुनरुत्पादित होते हैं।
लीक को किसी विशेष ट्यूनिंग की आवश्यकता नहीं होती। यह स्टॉक events {} कॉन्फ़िग पर काम करता है, जिसका डिफ़ॉल्ट worker_connections (512) एरिना का आकार ऐसा रखता है कि मुक्त अनुरोध चंक glibc bin में पहुँचता है जिसमें अभी भी एरिना और हीप पॉइंटर मौजूद होते हैं, जिन्हें अत्यधिक बड़ा लीक बफर पुनः उपयोग कर लेता है। केवल असामान्य रूप से कम worker_connections (~256 से नीचे) इससे बचता है; प्रोडक्शन मान (512-1024) सभी लीक करते हैं।
एक स्टैटिक कॉन्फ़िग स्कैनर जो बिना कुछ एक्सप्लॉइट किए कमज़ोर पैटर्न को चिह्नित करता है: https://github.com/0xCyberstan/CVE-2026-42533-Config-Scanner
यह एक पैच किए गए, सार्वजनिक रूप से प्रकट किए गए भेद्यता को लक्षित करता है। यह रक्षकों द्वारा जोखिम सत्यापन और शोध पुनरुत्पादन के लिए मौजूद है। इसे केवल उन nginx के विरुद्ध चलाएँ जिनके स्वामी आप हैं या जिनके परीक्षण के लिए आप स्पष्ट रूप से अधिकृत हैं। 1.30.4 या 1.31.3 में अपग्रेड करें।
| मोड | उद्देश्य |
|---|
poc.py --crash | हीप ओवरफ़्लो दागता है; ASan बिल्ड पर यह ngx_http_script_copy_capture_code पर राइट साइज़ और स्टैक प्रिंट करता है। |
poc.py --leak | सूचना लीक: अत्यधिक बड़े रिस्पॉन्स बॉडी से libc और हीप पॉइंटर बाहर निकालता है। |
poc.py --rce | पूर्ण प्री-ऑथ RCE। सामान्य सिंगल शॉट (configs/nginx_poc.conf), प्रति प्रयास ~66%, चूक जाने पर दोबारा चलाएँ। |
poc.py --rce-det | पूर्ण प्री-ऑथ RCE, नियंत्रित configs/nginx_det.conf के विरुद्ध डिटर्मिनिस्टिक। |
| स्क्रिप्ट | उद्देश्य |
|---|
exploits/leak_multi.py | दो और इवैल्यूएटरों (return, set) के माध्यम से सूचना लीक; प्रत्येक libc+हीप पॉइंटर /proc/<pid>/maps के विरुद्ध पुष्टि किया गया। स्टॉक कॉन्फ़िग। |
exploits/test_all_sites.py | AddressSanitizer वैलिडेटर जो सभी 13 ओवरफ़्लो कॉल साइटों (http + stream) को दागता है। |
exploits/named_capture_poc.py | r->variables[] / copy_var_code के माध्यम से नामित-कैप्चर (?P<name>...) वैरिएंट; दूसरा मूल कारण। |
| लक्षण | कारण | क्या करें |
|---|
--leak कोई पॉइंटर नहीं दिखाता, या --rce / --rce-det कभी सफल नहीं होते | आप ASan बिल्ड पर हैं; AddressSanitizer मुक्त स्मृति को विषाक्त (poison) कर देता है, इसलिए अवशेष में कोई वास्तविक पॉइंटर नहीं होते | क्लीन objs.dbg बिल्ड का उपयोग --leak, --rce, --rce-det और leak_multi.py के लिए करें। ASan objs बिल्ड केवल --crash, test_all_sites.py और named_capture_poc.py के लिए है। |
--rce केवल लगभग 3 में से 2 प्रयासों में सफल होता है | सामान्य कॉन्फ़िग के विरुद्ध सिंगल शॉट; मुक्त ट्रिगर-बॉडी का स्थान बदलता रहता है | अपेक्षित है। चूक जाने पर वर्कर क्रैश होकर पुनः आरंभ हो जाता है, इसलिए बस दोबारा चलाएँ। डिटर्मिनिस्टिक सिंगल शॉट के लिए --rce-det उपयोग करें। |
--rce-det हर बार No RCE. Recalibrate PL_OFF/HEAP_PAGE_OFF प्रिंट करता है | PL_OFF आपके बिल्ड, glibc, कॉन्फ़िग और nginx -p प्रीफ़िक्स पथ की लंबाई के लिए विशिष्ट है। शामिल किया गया मान इस रिपॉज़िटरी के डेव बिल्ड के लिए है जिसे -p run के साथ लॉन्च किया गया है | exploits/calibrate.py चलाएँ, यह जो PL_OFF प्रिंट करे उसे exploits/poc.py में चिपकाएँ, और nginx को वही -p प्रीफ़िक्स देकर शुरू करें जो आपने calibrate.py को दिया था (README में -p run उपयोग होता है)। |
--rce-det कभी-कभी 0x0a (regex-hostile) ... retry प्रिंट करता है | एक ASLR ड्रॉ ने किसी पते में 0x0a (न्यूलाइन) बाइट डाल दिया, जिसे map regex के माध्यम से नहीं भेजा जा सकता | यह विफलता नहीं है। दोबारा चलाएँ; अगला ड्रॉ लगभग हमेशा इससे बच जाता है। |
nginx या calibrate.py: bind() to 127.0.0.1:8950 failed (Address already in use) | पिछला nginx अभी भी पोर्ट पर काबिज़ है | pkill -x nginx चलाएँ, एक सेकंड प्रतीक्षा करें, फिर पुनः प्रयास करें। 8950 पर केवल एक nginx रखें। |
कोई स्टैंडअलोन स्क्रिप्ट nginx not found प्रिंट करती है | NGINX_BIN सेट नहीं है या गलत बिल्ड की ओर इंगित कर रहा है | NGINX_BIN सेट करें (leak_multi.py के लिए क्लीन बिल्ड, वैलिडेटरों के लिए ASan बिल्ड)। |
किसी कॉन्फ़िग, स्क्रिप्ट या nginx बाइनरी के लिए No such file | आप रिपॉज़िटरी रूट में नहीं हैं | पहले रिपॉज़िटरी रूट में cd करें; हर कमांड इसे मान लेता है (exploits/..., configs/..., ../nginx-1.30.1/...)। |
| लीक एक कॉन्फ़िग पर काम करता है पर दूसरे पर नहीं | ~256 से कम worker_connections एरिना को सिकोड़ देता है, जिससे मुक्त चंक में कोई पॉइंटर नहीं बचता | सामान्य worker_connections (512 से 1024) उपयोग करें। प्रोडक्शन मान सभी लीक करते हैं। |