Threat Intelligence

CVE-2026-6471 PostGREShell : le compte de réplication PostgreSQL qui charge la bibliothèque de votre choix

Admin CyberAfrik 08 September 2026 26 lectures
CVE-2026-6471 PostGREShell : le compte de réplication PostgreSQL qui charge la bibliothèque de votre choix

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 2026Cyera Research signale le défaut à l'équipe sécurité PostgreSQL, avec analyse de cause racine et PoC Windows
27 février 2026PostgreSQL confirme la vulnérabilité
16 mars 2026L'équipe PostgreSQL annonce un correctif dans une version mineure planifiée
14 mai 2026Date initialement prévue pour la version mineure et l'avis public, CVE-2026-6471 assignée
22 août 2026Publication effective des versions corrigées
1er septembre 2026Publication de l'analyse Cyera
7 septembre 2026Reprise 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.

PlateformePrérequisLivraison de la bibliothèque
WindowsAccès réseau uniquementChemin 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 NFSAutomount /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, KubernetesL'attaquant sait déjà écrire un fichier sur le disqueTraversé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

Vue infrastructure de la chaine PostGREShell

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.

TypeValeur
Commande protocoleCREATE_REPLICATION_SLOT provenant d'une adresse IP non attendue
Nom de pluginNom de plugin de sortie contenant un slash, un antislash, une double parenthèse de traversée ou un préfixe UNC
Nom de slotSlot de réplication au nom inhabituel, hors nomenclature des outils de sauvegarde en place
Flux réseauConnexion SMB sortante (TCP/445) initiée par le processus PostgreSQL
Flux réseauMontage NFS sortant (TCP/UDP 2049) déclenché depuis le serveur de base de données
ConfigurationAjout non tracé dans shared_preload_libraries
ConfigurationRègle trust ou 0.0.0.0/0 apparue dans pg_hba.conf
CatalogueModification 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.

TactiqueTechniqueIDJustification
Accès initialValid AccountsT1078La chaîne démarre avec un compte REPLICATION légitime, obtenu par fuite, réutilisation ou configuration trop large
ExécutionShared ModulesT1129Chargement d'une bibliothèque partagée par dlopen() ou LoadLibrary() avec exécution de _PG_init()
ExécutionCommand and Scripting InterpreterT1059COPY ... TO PROGRAM disponible une fois le superutilisateur obtenu
Élévation de privilègesExploitation for Privilege EscalationT1068Écriture directe dans pg_authid en contournant l'exécuteur SQL et ses ACL
PersistanceServer Software ComponentT1505Enregistrement du plugin dans shared_preload_libraries pour rechargement à chaque backend
PersistanceModify Authentication ProcessT1556Réécriture de pg_hba.conf pour autoriser les connexions sans mot de passe
Évasion défensiveImpair DefensesT1562Hook faisant retourner autorisé à chaque vérification de permission
Accès aux identifiantsCredentials from Password StoresT1555Lecture de secrets applicatifs et d'identifiants stockés en base une fois superutilisateur
Accès aux identifiantsUnsecured Credentials: Private KeysT1552.004pg_read_file() sur /etc/shadow et sur les clés privées lisibles par postgres
CollecteData from Information RepositoriesT1213Lecture de l'intégralité des bases après élévation

Remédiation : checklist opérationnelle

  1. 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.
  2. 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.
  3. 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.
  4. 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.
  5. Désactiver autofs sur les serveurs de bases où il n'est pas nécessaire, en particulier sur les distributions RHEL, CentOS et Rocky.
  6. 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.
  7. Journaliser et alerter sur les commandes CREATE_REPLICATION_SLOT, en particulier sur les noms de plugin contenant des séparateurs de chemin.
  8. 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.
  9. Auditer pg_authid à la recherche de rôles disposant d'attributs de superutilisateur non justifiés par une opération tracée.
  10. 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

Tags : CVE-2026-6471PostGREShellPostgreSQLréplication logiquedlopenCyera Researchélévation de privilègespg_authid
Partager cet article