
Ejecución remota de código fiable desde un único RESTORE manipulado en Redis con jemalloc —
sin comando DEBUG, sin /proc, sin gdb, sin ROP, con ASLR activado. Ejecuta el comando del
atacante como el proceso redis (root en las imágenes predeterminadas).
🔒 Repositorio privado — solo investigación de seguridad autorizada / divulgación coordinada. No redistribuir. El fallo está corregido upstream (6.2.22 / 7.2.14 / 7.4.9 / 8.2.6 / 8.4.3 / 8.6.3, commit
b9dde6fc); esto apunta a la ruta previa al parche.
La técnica está probada de extremo a extremo — una ejecución limpia en el banco de pruebas de
referencia disparó system("id") → uid=0(root) (con ASLR activado, enable-debug-command no),
confirmado el 02-07-2026. En este reempaquetado de un solo archivo, se ha confirmado que las
primeras fases funcionan (doble liberación, solapamiento, lectura arbitraria → PIE y
libc/system recuperados correctamente en ambos casos), pero la fuga final — blob_base vía
OFF_BLOBROBJ — es sensible a la secuencia de asignación y la constante incluida no se transfirió
limpiamente al groom de exploit.py (blob_read_short repetido). Recalibra OFF_BLOBROBJ para tu
compilación+secuencia exactas (WRITEUP.md §7) antes de confiar en él; el código de disparo de
referencia es el harness de desarrollo pwn.py/pwnd.py. Todo lo demás está validado.
exploit.py — PoC autocontenido (solo stdlib). Construye los offsets en el diccionario PROFILE de la parte superior.WRITEUP.md — análisis técnico completo (fallo, groom, lectura arbitraria sin DEBUG, determinismo, cierre).python3 exploit.py --host <target> --port 6379 --cmd 'id' --tries 40
# fires system("<cmd>") as the redis process; verify out-of-band or use a reverse-shell --cmd.
Validado en Redis 8.6.2 (8a8f1a3bb), jemalloc-5.3.0, x86-64, glibc bookworm, ASLR=2,
enable-debug-command no. Para una compilación diferente, recalibra los offsets de PROFILE —
consulta WRITEUP.md §7.
EVAL→clo → lectura arbitraria de PIE (clo+33) → lectura arbitraria de system (free@GOT) +
blob_base (blob_robj) → colocar un dictType{hashFunction=system} falso en un blob de 16 MB →
forjar h2->dict->type → HGET h2 "<cmd>" == system("<cmd>").