
Proof-of-Concept-Exploit für CVE-2026-6471, der eine Privilegieneskalation in PostgreSQL über logisches Decoding von `dlopen` demonstriert, um beliebige Codeausführung und eine Superuser-Hintertür zu erreichen.
Das logische Decoding von PostgreSQL erlaubt einer Rolle ohne Superuser-Rechte, die über das
REPLICATION-Privileg verfügt, einen logischen Replikations-Slot zu erstellen und das
Ausgabe-Plugin zu wählen. Bei betroffenen Versionen gibt es keine Autorisierungsprüfung für diese
Wahl, sodass der Server dlopen() auf das ausführt, worauf der Plugin-Name verweist. Die Benennung
eines Bibliothekspfads führt den Code dieser Bibliothek im Postgres-Backend aus, als das
Betriebssystemkonto, das den Server ausführt. Das ist eine Ausführung beliebigen Codes als der
OS-Benutzer des Datenbankservers, was für eine Datenbank, die die Anwendungsdaten enthält,
praktisch einer Serverübernahme entspricht.
Behoben in PostgreSQL 18.6, 17.11, 16.15, 15.19 und 14.24 durch die
output_plugin_libraries-Allowlist (Standard pgoutput, test_decoding).
Alles, was nicht auf dieser Liste steht, erzeugt nun einen Fehler mit library "X" may not be used as an output plugin, bevor ein dlopen stattfindet.
Führen Sie dieselben Schritte gegen beide Builds aus, und nur die PostgreSQL-Version ändert sich. Ein Konto mit niedrigen Privilegien (LOGIN + REPLICATION, kein Superuser, kein OS-Zugriff) tut das, was ein normaler logischer Decoding-Abonnent tut, und bittet dann den Server, eine beliebige Bibliothek als Ausgabe-Plugin zu laden. Auf dem verwundbaren Build läuft diese Bibliothek als Postgres-OS-Benutzer und pflanzt eine persistente Superuser-Hintertür-Rolle, sodass ein Replikations-only-Konto den Lauf mit einem funktionierenden Superuser-Login beendet.
cve-2026-6471-postgres-logical-decoding-dlopen.txt ist eine Exploitmatic-
Lösung (.txt): Daten plus Asserts, kein Code. Die Laufzeit spielt sie gegen die
Box ab. Die Lösung liefert pwn.so zur Laufzeit aus (base64 in der Datei),
steuert das SQL als Rolle mit niedrigen Replikationsprivilegien und loggt sich dann als
Superuser-Hintertür-Rolle ein, die das Payload gepflanzt hat.pwn.c ist der Quellcode der Payload-Bibliothek und pwn.so ihr Build: ein einzelner ELF-
Konstruktor, der als Postgres-OS-Benutzer läuft, sich über den lokalen
Socket als Datenbank-Superuser verbindet (peer/trust) und die persistente
Rolle cve6471_backdoor LOGIN SUPERUSER PASSWORD 'BackdoorPass1' erstellt. Sie läuft
nur, wenn der Server die Bibliothek tatsächlich lädt, d. h. nur auf einem verwundbaren
Build. Build mit gcc -Os -shared -fPIC -o pwn.so pwn.c auf einer Linux-libc,
die zum Server-Image passt.Voraussetzungen: Sie haben Docker-Zugriff.
Der Ordner lab/ enthält das exakte Replikat, das zur Verifizierung dieses PoC verwendet wurde. Bauen und
starten Sie die beiden Boxen (verwundbar = postgres 16.14, gepatcht = postgres 16.15):
docker build -t pg-6471-vuln -f lab/Dockerfile.vuln lab
docker build -t pg-6471-fixed -f lab/Dockerfile.fixed lab
docker run -d --name pg-6471-vuln -p 15432:5432 -e POSTGRES_PASSWORD=lab-super-pw pg-6471-vuln
docker run -d --name pg-6471-fixed -p 15433:5432 -e POSTGRES_PASSWORD=lab-super-pw pg-6471-fixed
Beide Boxen laufen mit dem offiziellen Stock-Postgres-Image mit wal_level=logical.
Das Init-Skript lab/01-repro.sh erstellt die Rolle mit niedrigen Privilegien, die die
Lösung verwendet, repro_rep LOGIN REPLICATION PASSWORD 'repropass', die
kein Superuser ist.
Dann die Lösung abspielen:
exploitmatic run cve-2026-6471-postgres-logical-decoding-dlopen.txt 127.0.0.1
Auf die gepatchte Box mit einer Variablen-Überschreibung zeigen, ohne Dateibearbeitung:
exploitmatic run cve-2026-6471-postgres-logical-decoding-dlopen.txt 127.0.0.1 \
--var ctr=pg-6471-fixed
ctr ist der Docker-Container, pw ist das Passwort der Replikationsrolle.
| Ziel | Ergebnis |
|---|---|
| postgres 16.14 (verwundbar), wal_level=logical | 4/4 verifiziert, Superuser-Hintertür-Login funktioniert |
| postgres 16.15 (gepatcht), wal_level=logical | 3/4 nicht verifiziert, keine Hintertür |
Nur für autorisierte Tests und Forschung, auf Systemen, die Sie besitzen oder für die Sie die Erlaubnis zum Testen haben. Dieser PoC demonstriert eine Privilegieneskalation nach der Authentifizierung: Er erfordert ein bestehendes Datenbankkonto mit niedrigen Privilegien mit dem REPLICATION-Attribut sowie eine Möglichkeit, vom Angreifer kontrollierten Code dort zu platzieren, wo der Postgres-OS-Benutzer ihn laden kann. Es ist kein Remote-Angriff ohne Authentifizierung. Der geladene Code erreicht den Datenbank-Superuser, weil das OS-Konto, das den Server besitzt, sich über den lokalen Socket als Superuser verbinden kann (peer/trust), was eine Standard-Praxis bei PostgreSQL-Bereitstellungen ist.
| Schritt | verwundbar 16.14 | gepatcht 16.15 |
|---|
| Recon (Rolle ist Replikation, kein Superuser) | bestanden | bestanden |
| Baseline (logischer Slot mit integriertem pgoutput) | bestanden | bestanden |
| Trigger (Slot-Plugin = Pfad der Angreifer-Bibliothek) | Server lädt sie | vor dem Laden abgelehnt |
| Übernahme (Login als gepflanzte Superuser-Hintertür) | Superuser | keine solche Rolle |