Rapport CTI technique du 8 septembre 2026
Résumé exécutif
Cyera Research a publié le 1er septembre 2026 l'analyse de CVE-2026-6471, surnommée PostGREShell, un défaut d'autorisation dans le chemin de réplication logique de PostgreSQL. Quand un client crée un slot de réplication logique, le nom du plugin de sortie fourni dans la commande CREATE_REPLICATION_SLOT part directement vers load_external_function, sans passer par check_restricted_library_name(), le garde-fou qui force les non-superutilisateurs à charger uniquement depuis un répertoire administré. Le parseur du protocole de réplication accepte des slashs, des antislashs, des séquences de traversée et des chemins UNC Windows entre guillemets doubles. Un compte disposant du seul attribut REPLICATION, celui que portent tous les outils de sauvegarde, les standbys et les pipelines CDC, obtient donc un dlopen() ou un LoadLibrary() sur un chemin qu'il choisit, avec exécution immédiate de _PG_init() dans le processus serveur.
Le défaut est présent dans toutes les versions depuis la 9.4, soit depuis 2014, et confirmé sur la 18.2. Sur Windows, il est exploitable entièrement à distance : PostgreSQL va chercher la DLL sur un partage SMB contrôlé par l'attaquant, sans qu'aucun fichier ne soit déposé sur la cible. Une fois le code chargé, la bibliothèque écrit directement dans pg_authid pour se donner tous les attributs de superutilisateur sans jamais passer par l'exécuteur SQL, donc sans qu'aucun contrôle d'ACL ne se déclenche, puis installe trois mécanismes de persistance qui se couvrent mutuellement. Le score CVSS publié est de 7.2. Aucune exploitation active n'est documentée et la CVE ne figure pas au catalogue KEV de la CISA au 8 septembre, mais une chasse menée par Cyera sur VirusTotal a remonté 114 plugins PostgreSQL malveillants déjà présents dans la nature, entre trojans, mineurs de cryptomonnaie et reverse shells.
Chronologie
| Date | Événement |
|---|---|
| 2014 (PostgreSQL 9.4) | Introduction de la réplication logique et du chargement de plugin de sortie non validé |
| 21 février 2026 | Cyera Research signale le défaut à l'équipe sécurité PostgreSQL, avec analyse de cause racine et PoC Windows |
| 27 février 2026 | PostgreSQL confirme la vulnérabilité |
| 16 mars 2026 | L'équipe PostgreSQL annonce un correctif dans une version mineure planifiée |
| 14 mai 2026 | Date initialement prévue pour la version mineure et l'avis public, CVE-2026-6471 assignée |
| 22 août 2026 | Publication effective des versions corrigées |
| 1er septembre 2026 | Publication de l'analyse Cyera |
| 7 septembre 2026 | Reprise par SecurityWeek, SC Media, CSO Online et Security Affairs |
Fiche vulnérabilité
CVE-2026-6471 | CVSS 7.2 | PostgreSQL 9.4 à 18, toutes plateformes
Le mécanisme est un défaut d'autorisation manquante sur un chemin de chargement de code. Dans LoadOutputPlugin, le nom du plugin transite tel quel vers load_external_function(plugin, "_PG_output_plugin_init", false, NULL). La commande SQL LOAD passe, elle, un drapeau !superuser() qui déclenche la validation de chemin. Le chemin de réplication ne passe rien. Le correctif tient en deux lignes de C côté projet.
Conditions d'exploitation : un compte porteur de l'attribut REPLICATION, sans privilège superutilisateur ni administrateur, la configuration wal_level = logical sur le serveur, et un moyen d'amener la bibliothèque jusqu'au chargeur. Ce dernier point est le seul qui varie selon la plateforme.
| Plateforme | Prérequis | Livraison de la bibliothèque |
|---|---|---|
| Windows | Accès réseau uniquement | Chemin UNC via SMB (port 445). PostgreSQL télécharge la DLL depuis le serveur de l'attaquant, rien n'est déposé sur la cible |
| Linux ou macOS avec automontage NFS | Automount /net actif (macOS avant Catalina par défaut, RHEL, CentOS et Rocky avec autofs) | Traversée de chemin vers /net/hote/ déclenchant un montage NFS automatique (port 2049) |
| Linux standard, Docker, Kubernetes | L'attaquant sait déjà écrire un fichier sur le disque | Traversée de chemin vers un fichier .so local déposé par un autre canal |
PoC disponible : oui pour le principe. Cyera indique que l'exploit Windows tient en trois lignes de Python et a transmis un PoC à l'équipe PostgreSQL, mais ne publie pas de code d'exploitation clé en main. Aucun exploit public complet n'a été observé au 8 septembre 2026.
Patch : versions 18.6, 17.11, 16.15, 15.19 et 14.24, publiées le 22 août 2026.
Diagramme de la chaîne d'attaque

Reconstruction à partir de l'analyse Cyera Research du 1er septembre 2026. La variante représentée est le chemin Windows entièrement distant.
Analyse technique
Étape 1 : le compte que personne ne surveille
L'attribut REPLICATION existe pour permettre le streaming de la journalisation transactionnelle. La documentation PostgreSQL le décrit comme nécessaire pour initier une réplication en flux, pas pour exécuter du code. Il se retrouve donc sur les comptes de sauvegarde, les serveurs de secours, les pipelines de capture de changements type Debezium et les sondes de supervision qui lisent le WAL. Dans la plupart des politiques internes, ce compte est classé comme plomberie opérationnelle à faible risque, ce qui se traduit par des mots de passe longtemps inchangés, des règles pg_hba.conf larges et une absence de surveillance de ses connexions.
La réplication logique, activée par wal_level = logical, expose les changements sous forme d'événements de table. Le client crée un slot et nomme le plugin de sortie qui met le flux en forme, pgoutput ou wal2json par exemple. C'est ce nom qui devient un chemin de chargement.
Étape 2 : du nom de plugin au dlopen
Les plugins PostgreSQL sont du code compilé (.so, .dll, .dylib) chargé dans le processus du serveur. À l'ouverture, PostgreSQL exécute immédiatement _PG_init() avec les privilèges complets du processus. Le projet a bien anticipé ce risque, mais uniquement sur le chemin SQL : check_restricted_library_name() interdit les chemins absolus et les traversées pour les non-superutilisateurs. Le chemin de réplication ne l'appelle jamais, et le parseur du protocole tolère à peu près tout caractère entre guillemets doubles.
Sur Windows, le résultat est direct. Un appel LoadLibrary sur un chemin UNC fait résoudre celui-ci par le système, qui ouvre une connexion SMB sortante, récupère la DLL, la mappe dans le processus PostgreSQL et exécute son _PG_init(). L'attaquant n'a besoin d'aucune écriture sur la cible : il héberge le fichier chez lui et envoie une commande. Sur les systèmes Unix avec autofs, la traversée vers /net/hote/ produit le même effet par un montage NFS déclenché à la volée.
Étape 3 : du compte de sauvegarde au superutilisateur
À ce stade, le code tourne sous l'utilisateur système postgres, mais l'attaquant reste un simple compte de sauvegarde du point de vue SQL. Cette asymétrie ne dure pas, parce que PostgreSQL possède deux niveaux de sécurité très inégaux. Le niveau SQL, avec ses ACL, ses rôles et sa sécurité au niveau ligne, est solide et éprouvé. Le niveau C n'existe pas : une bibliothèque chargée par dlopen() partage l'espace d'adressage du serveur, sans bac à sable ni contrôle sur les appels aux API internes.
Le plugin appelle donc une fonction interne pour devenir le superutilisateur d'amorçage sur la session, puis écrit directement dans pg_authid, la table de catalogue qui définit qui est superutilisateur, en basculant tous les drapeaux de privilège à vrai. Cette écriture ne passe pas par l'exécuteur SQL, donc aucun contrôle d'ACL ne se déclenche et le résultat est indiscernable d'un ALTER ROLE légitime dans le catalogue. Pour verrouiller le tout, un hook est installé qui fait répondre autorisé à chaque vérification de permission.
Le superutilisateur PostgreSQL n'est pas un privilège purement base de données : il donne COPY ... TO PROGRAM pour exécuter des commandes système, pg_read_file() pour lire des fichiers arbitraires comme /etc/shadow ou des clés privées, et lo_export() pour écrire partout où postgres peut écrire.
Étape 4 : trois persistances qui se couvrent
Le plugin décrit par Cyera installe trois mécanismes en parallèle. Il réécrit pg_hba.conf pour autoriser n'importe quelle connexion sous n'importe quel rôle sans mot de passe, puis recharge la configuration immédiatement. Il se copie à un emplacement stable et s'enregistre dans shared_preload_libraries, ce qui le fait recharger dans chaque nouveau backend après un redémarrage. Enfin, il réapplique la modification de superutilisateur si un administrateur la corrige. Un administrateur qui trouve et nettoie une seule de ces trois portes laisse les deux autres actives.
Étape 5 : une classe de vulnérabilité qui revient
Le schéma est connu : un serveur charge des extensions, le nom d'extension n'est pas validé, un attaquant obtient de l'exécution de code. Redis en est le cas d'école avec MODULE LOAD, exploité par plusieurs botnets, dont HeadCrab qui a infecté plus de 1 200 serveurs pour du minage, et plus récemment RediShell (CVE-2025-49844, CVSS 10.0), resté exposé environ treize ans. Le même motif a touché OpenVPN, MySQL et ses dérivés MariaDB et Percona, MongoDB via un chemin de recherche dlopen() non contrôlé, et SQLite JDBC via une URL malveillante. La cause structurelle est la même partout : le code de chargement de modules est écrit en dehors du modèle de sécurité principal, et personne ne fait le lien entre les deux chemins.
Indicateurs de compromission
Aucun IOC réseau ni empreinte de fichier n'a été publié pour une campagne d'exploitation de CVE-2026-6471, car aucune n'est documentée à ce jour. Les éléments ci-dessous sont des indicateurs comportementaux tirés du mécanisme lui-même et des recommandations de Cyera.
| Type | Valeur |
|---|---|
| Commande protocole | CREATE_REPLICATION_SLOT provenant d'une adresse IP non attendue |
| Nom de plugin | Nom de plugin de sortie contenant un slash, un antislash, une double parenthèse de traversée ou un préfixe UNC |
| Nom de slot | Slot de réplication au nom inhabituel, hors nomenclature des outils de sauvegarde en place |
| Flux réseau | Connexion SMB sortante (TCP/445) initiée par le processus PostgreSQL |
| Flux réseau | Montage NFS sortant (TCP/UDP 2049) déclenché depuis le serveur de base de données |
| Configuration | Ajout non tracé dans shared_preload_libraries |
| Configuration | Règle trust ou 0.0.0.0/0 apparue dans pg_hba.conf |
| Catalogue | Modification de rolsuper dans pg_authid sans commande ALTER ROLE correspondante dans les journaux |
MITRE ATT&CK
Cyera n'a pas publié de cartographie ATT&CK. Le tableau suivant est une lecture technique établie à partir des mécanismes décrits dans l'analyse.
| Tactique | Technique | ID | Justification |
|---|---|---|---|
| Accès initial | Valid Accounts | T1078 | La chaîne démarre avec un compte REPLICATION légitime, obtenu par fuite, réutilisation ou configuration trop large |
| Exécution | Shared Modules | T1129 | Chargement d'une bibliothèque partagée par dlopen() ou LoadLibrary() avec exécution de _PG_init() |
| Exécution | Command and Scripting Interpreter | T1059 | COPY ... TO PROGRAM disponible une fois le superutilisateur obtenu |
| Élévation de privilèges | Exploitation for Privilege Escalation | T1068 | Écriture directe dans pg_authid en contournant l'exécuteur SQL et ses ACL |
| Persistance | Server Software Component | T1505 | Enregistrement du plugin dans shared_preload_libraries pour rechargement à chaque backend |
| Persistance | Modify Authentication Process | T1556 | Réécriture de pg_hba.conf pour autoriser les connexions sans mot de passe |
| Évasion défensive | Impair Defenses | T1562 | Hook faisant retourner autorisé à chaque vérification de permission |
| Accès aux identifiants | Credentials from Password Stores | T1555 | Lecture de secrets applicatifs et d'identifiants stockés en base une fois superutilisateur |
| Accès aux identifiants | Unsecured Credentials: Private Keys | T1552.004 | pg_read_file() sur /etc/shadow et sur les clés privées lisibles par postgres |
| Collecte | Data from Information Repositories | T1213 | Lecture de l'intégralité des bases après élévation |
Remédiation : checklist opérationnelle
- Appliquer la mise à jour mineure de PostgreSQL publiée le 22 août 2026 : 18.6, 17.11, 16.15, 15.19 ou 14.24 selon la branche. Les branches antérieures à la 14 sont hors support et doivent être migrées.
- Inventorier tous les rôles portant l'attribut REPLICATION sur chaque instance, y compris les instances managées, et retirer l'attribut à tous ceux qui ne s'en servent pas réellement.
- Restreindre les entrées de réplication de pg_hba.conf à des adresses IP connues. Aucune règle de réplication ne doit accepter 0.0.0.0/0.
- Bloquer au pare-feu les flux SMB (445) et NFS (2049) sortants depuis les serveurs de bases de données. Cette mesure seule supprime les deux chemins d'exploitation entièrement distants.
- Désactiver autofs sur les serveurs de bases où il n'est pas nécessaire, en particulier sur les distributions RHEL, CentOS et Rocky.
- Vérifier si wal_level est réellement positionné sur logical : sur une instance qui n'a pas besoin de réplication logique, revenir à replica retire la surface d'attaque.
- Journaliser et alerter sur les commandes CREATE_REPLICATION_SLOT, en particulier sur les noms de plugin contenant des séparateurs de chemin.
- Comparer le contenu actuel de shared_preload_libraries et de pg_hba.conf avec la configuration de référence, et rechercher toute bibliothèque non attendue dans les répertoires d'extensions.
- Auditer pg_authid à la recherche de rôles disposant d'attributs de superutilisateur non justifiés par une opération tracée.
- Faire tourner les mots de passe des comptes de réplication après application du correctif, en partant du principe qu'un compte non surveillé depuis des années peut déjà avoir fuité.
Sources
- PostGREShell: The database powering much of the internet had an open door for 12 years, Vladimir Tokarev, Cyera Research, 1er septembre 2026
- 12-Year-Old PostgreSQL Vulnerability Enables Database, Server Takeover, SecurityWeek
- Decade-old PostgreSQL flaw turns backup account into a backdoor, CSO Online
- PostgreSQL Hit by 12-Year-Old Vulnerability Allowing Server Takeover, Security Affairs
- PostGREShell vulnerability allows server takeover, SC Media