
PoC autonome et analyse pour CVE-2026-94300, une utilisation après libération (use-after-free) GSS-TSIG dans BIND 9.20.29, avec un modèle assisté par débogueur de la chaîne allant de la fuite à l'exécution de code.
Remarque : cette analyse et ce PoC ont été produits en grande partie avec l'aide de l'IA (« patchwork IA »). Chaque affirmation concernant le code, le diff et les mesures doit être vérifiée par rapport aux sources citées avant d'être utilisée.
Dossier PoC autonome pour la chaîne d'exploitation de CVE-2026-94300 (BIND 9.20.29 avec GSS-TSIG, krb5 1.20.1, jemalloc 5.3.0).
Ce qui est prouvé ici : un ensemble d'adresses divulgué (ici depuis gdb) suffit pour construire une exécution de code dans
le processus named à partir des primitives mesurées. L'exploit consomme la fuite issue de
docker logs ; il ne contient aucun littéral d'adresse.
Ce qui est explicitement un modèle ici (et présenté comme tel dans le rapport) :
| Hypothèse | Raison |
|---|---|
| Fuite depuis gdb | La CVE ne possède pas de primitive de fuite d'information ; une fuite réelle devrait provenir d'un autre bug |
ASLR désactivé (setarch -R) | sans fuite, il n'y a pas d'adresses de tas ou de code |
| Contrôle du contenu d'objet injecté via gdb | la récupération de l'emplacement de 8 octets libéré n'a pas réussi dans le chemin réel avec les moyens examinés ici (4,7 M tentatives, 0 succès) — un obstacle documenté, non une preuve d'impossibilité |
Aucun RCE distant démontré et aucune persistance. La commande est fournie via --cmd sur l'exploit : host/exploit.py la transmet par le canal de contrôle Docker (docker exec, la même autorité que l'opérateur possède déjà) dans le conteneur ; l'exploit lui-même
n'envoie que les adresses divulguées et le paquet capturé. La charge utile écrit en outre la ligne RCE-PROOF (pour vérification) et termine named.
sequenceDiagram
participant R as Researcher (host)
participant V as Container: named 9.20.29 + gdb
participant L as docker logs
R->>V: docker run -p 127.0.0.1:15353:53/udp
V->>V: TKEY capture (no send), gdb breaks on dns_db_currentversion
V->>L: LEAK: db=…, methods=…, heap=…, wire_b64=… (sha256)
V->>V: model armed, waits for host replay
R->>L: read docker logs + validate (11 checks)
R->>V: docker exec: --cmd to /tmp/rce-payload-cmd
R->>V: UDP replay of the leaked signed packet to 15353
V->>V: krb5_k_free_key → free(db) → reclaim → fake dns_db_t
V->>V: dns_db_currentversion → jmp *methods+0x30 → payload
R->>V: docker exec cat /tmp/rce-proof
| Chemin | Objectif |
|---|---|
docker/Dockerfile | Image victime : BIND 9.20.29 depuis l'archive tarball ISC + gdb + KDC + pilotes de labo |
etc/ | krb5.conf, kdc.conf, named.conf, zone (copiés dans /etc par l'image) |
host/exploit.py | Exploit hôte : lit docker logs, valide, rejoue sur UDP, vérifie le marqueur |
lab/rce_victim.sh | Pilote dans le conteneur : named sous gdb, capture sans envoi, fuite, attente |
lab/rce_model.py | Modèle gdb : points d'arrêt, bloc de fuite, armement, observation de la répartition |
lab/rce_leak.py | Étape de fuite : adresses + wire_b64 → stdout/fichier |
lab/rce_exploit.py | Étape d'exploit dans le conteneur : construit l'objet factice à partir de la fuite, récupération, répartition |
lab/rce_shim.c | Shim de page fixe : table factice, modèle dns_db_t factice, charge utile |
lab/replay-lab.py | Capture TKEY (--no-send) |
lab/gss_context_lab.py | Assistant de contexte GSS pour la capture |
lab/start.sh, lab/named.replay.conf | Amorçage KDC/keytab/zone, configuration de named |
RACE.md | Explication de la course sur le contexte GSS-TSIG partagé : partage, accès, déclenchement, mesures, portée |
VERIFY.md | Vérification des trois affirmations par rapport au diff source 9.20.29 → 9.20.30 (verrouillage GSS-TSIG, vidage destructif du trousseau de clés, portée de la RCE) |
EXPLOIT.md | Description de l'exploit avec preuves de code et Mermaid |
USAGE.md | Construction, exécution, sorties attendues, dépannage |
ANAYLSE.md | Addendum de divulgation prêt à publication (réconciliation d'impact DoS vs. RCE potentielle, versions affectées, atténuation, détection) — sans primitives d'exploit |
ANALYZE.md | Version anglaise de l'addendum de divulgation |
(Ce fichier est README.md ; les autres documents du PoC existent également sous les noms RACE.md, VERIFY.md,
EXPLOIT.md, USAGE.md.)
Uniquement Docker + accès Internet au moment de la construction. L'image construit BIND 9.20.29 elle-même à partir de l'archive
tarball officielle ISC (https://downloads.isc.org/isc/bind9/9.20.29/bind-9.20.29.tar.xz, SHA-256 épinglé),
avec --with-gssapi=yes, et installe gdb, le KDC MIT Kerberos et les pilotes de labo. Aucun BIND
de distribution, aucune image de base préconstruite nécessaire.
L'image contient une identité KDC jetable [email protected] (mot de passe attacker,
royaume EXAMPLE.TEST, KDC sur 127.0.0.1:88 dans le conteneur uniquement) — exclusivement pour ce labo, pas
pour des tests GSS-TSIG contre d'autres serveurs ; ne sortez pas le keytab du conteneur.
cd poc/CVE-2026-94300-poc
docker build -f docker/Dockerfile -t cve-2026-94300-victim .
# Terminal 1: container
docker run --rm --name cve-2026-94300-victim \
-p 127.0.0.1:15353:53/udp \
--security-opt seccomp=unconfined \
cve-2026-94300-victim # prints the LEAK block to stdout
# Terminal 2: exploit from the host, target + command as arguments
python3 host/exploit.py --ip 127.0.0.1 --port 15353 --cmd 'id > /tmp/bla'
docker exec cve-2026-94300-victim cat /tmp/bla # uid=0(root) …
Attendu (extrait) :
LEAK: db=0x7ffff6901c00
LEAK: db_methods=0x7ffff7c497c0
LEAK: payload=0x7ffff7fbe37b
LEAK: wire_len=3907
HOST-EXPLOIT-VALIDATE OK checks=11
HOST-EXPLOIT-REPLAY target=127.0.0.1:15353 bytes=3907
RCE-DISPATCH-INDIRECT target=0x7ffff7fbe37b (rce_payload) match=YES
RCE-PAYLOAD-EXECUTED RCE-PROOF pid=… uid=0 euid=0 db=0x7ffff6901c00
HOST-EXPLOIT-VERDICT payload_executed=YES marker=YES
Phrase de mise en garde : L'ISC classe CVE-2026-94300 comme distant, Élevé, CVSS 8.1 (AC:H) avec exécution de code potentielle. Ce qui est publiquement/reproductiblement établi est une corruption de mémoire déclenchée par rejeu, sans identifiants (use-after-free/double-free) sur le contexte GSS-TSIG partagé — de la classe DoS à corruption de tas. Un chemin vers l'exécution de code n'a jusqu'ici été démontré que sous des hypothèses de modèle assistées par débogueur (ASLR désactivé, adresses/contenus d'objets injectés) ; aucun RCE distant démontré n'existe.
Établi : étant donné une fuite, le RCE suit dans le processus cible. Non établi : une attaque distante sans fuite et sans gdb — la primitive de fuite d'information et l'étape de récupération atteinte manquent pour cela. Il s'agit d'un ensemble documenté d'obstacles, non d'une preuve d'impossibilité ; l'ISC porte la classe d'exécution de code comme potentielle. La base du code (bug de synchronisation, vidage destructif, ce que le correctif corrige et ce qu'il ne corrige pas) est vérifiée dans VERIFY.md par rapport au diff des deux arborescences ; le fonctionnement technique de la course est décrit dans RACE.md. Détails de l'exploit et preuves du code : EXPLOIT.md, exécution et options : USAGE.md. Divulgation prête à publication : ANALYZE.md.