
ASLR-unabhängige nginx-RCE-Kette PoC, die das PoolSlip-Heap-Over-Read-Leak (CVE-2026-9256) mit dem rift-Overflow (CVE-2026-42945) kombiniert, um system() auf Standard-nginx zu erreichen.
Erste öffentliche Verkettung zweier kürzlich offengelegter nginx-Rewrite-Engine-Bugs zu einem einzigen
ASLR-unabhängigen remote system() auf dem offiziellen nginx:1.30.0 Docker-Image
(Debian 13, glibc 2.41) — keine hartkodierten Adressen, kein nginx-Neustart, ~90 % pro frischem Worker.
$args-Heap-Over-Read → leakt live libc + Heap.is_args-Heap-Overflow (nur URL-sichere Bytes) → ein 2-Byte-Partial-
Overwrite eines limit_conn-Cleanup-Pointers → ngx_destroy_pool läuft ihn ab → system(cmd).Beide sind derselbe is_args-Two-Pass-Mismatch, gerichtet auf zwei Sinks. Vollständiger technischer Write-up: Writeup
Offenlegung & Sicherheit
- Beide CVEs sind bereits gepatcht und werden aktiv in freier Wildbahn ausgenutzt. Upgrade auf nginx 1.30.2 (stable) oder 1.31.1 (mainline) — beachte, dass
1.30.1rift behebt, aber weiterhin anfällig für PoolSlip ist, sodass nur1.30.2beide schließt. NGINX Plus: R36 P5 / R32 P7 / R37.0.1.1.- Dies wird ausschließlich zu Bildungs- und autorisierten Testzwecken veröffentlicht. Es läuft gegen das mitgelieferte lokale Docker-Lab — richte es nicht auf Infrastruktur, die dir nicht gehört oder für die du keine schriftliche Testgenehmigung hast.
| CVE | Spitzname | anfällig | behoben (nginx OSS) |
|---|---|---|---|
| CVE-2026-42945 | rift | 0.6.27 – 1.30.0 | 1.30.1 / 1.31.0 |
| CVE-2026-9256 | PoolSlip | 0.1.17 – 1.30.1 + 1.31.0 | 1.30.2 / 1.31.1 |
| Datei | Zweck |
|---|---|
nginx.conf | Eine glaubwürdige API-Gateway-Konfiguration (das Ziel — limit_conn, ein v1→v2-Migrations-Rewrite, ein Upload-Proxy, eine degradierte Suchseite). Kein Allocator-Tuning. |
run.sh | Startet das lokale Lab: offizielles nginx:1.30.0, das nginx.conf ausliefert, plus ein langsames Upstream, auf Host :19322. |
exp_official.py | Die vollständige Kette: PoolSlip-Leak → libc/Heap ableiten → Spray → Groom → rift-Partial-Overwrite → system(). |
exp_official.py), curl, Linux x86-64.run.sh verwendet perl (bereits im offiziellen nginx-Image enthalten) für das langsame Upstream, sodass kein zusätzliches Paket, keine slow_backend-Datei und kein Internet benötigt werden. Die nginx-Binary selbst bleibt unverändert.WRITEUP.md zu folgen, per docker exec hineingehen und apt-get install gdb file binutils ausführen, dann gef laden.git clone https://github.com/y198nt/Nginx-chain-Rift-Poolslip
cd Nginx-chain-Rift-Poolslip
bash run.sh # stock nginx:1.30.0 on http://127.0.0.1:19322
python3 exp_official.py --cmd 'id > /tmp/rce_proof' # leak → overwrite → system()
docker exec nginx-rift-official cat /tmp/rce_proof # → uid=101(nginx) ...
exp_official.py ist einmalig (~90 % pro frischem Worker): Es leakt einmal und feuert einmal. Wenn die
Proof-Datei leer ist, hat der Groom einen Slot daneben platziert — einfach erneut ausführen.
docker rm -f nginx-rift-official # tear the lab down
rewrite ^/search/((.*))$ /lookup?$1$2 lässt den Copy-Pass
r->args.len über den Puffer hinaus setzen; die degradierte /search-Seite reflektiert $args in den angrenzenden Heap.
Nach einem kurzen Warm-up setzen sich ein libpcre-Cluster-Pointer (fix 0xb0ad08 unterhalb von libc) und ein Heap-
Pointer an stabilen Offsets fest → libc_base und heap_base, nichts hartkodiert.limit_conn-Cleanup-Pointers — die ASLR-zufälligen hohen Bytes bleiben unberührt →
ASLR-unabhängig.ngx_pool_cleanup_t{handler=&system, data=cmd, next=0} umgeleitet; das Schließen des Opfers löst den Cleanup-Walk von ngx_destroy_pool aus →
system(cmd).Siehe Writeup für die vollständige Herleitung, gdb-Sessions und die Sackgassen/Pivots.
rewrite, dessen Ersetzung ? enthält und auf einen PCRE-
Capture ($1/$2) verweist, oder über ein verschachteltes Capture-Muster wie ^/x/((.*))$ → /y?$1$2. Prüfe Konfigurationen auf
diese und überarbeite das betroffene rewrite/set, bis gepatcht wurde.$args (oder eine beliebige aus der Anfrage stammende, zurückgegebene Variable) ist das, was den Over-Read
in ein Info-Leak verwandelt — reflektiere Request-Args nicht wörtlich.%2B/+-Fluten im URI-Pfad (GET /search/+++…), 503s von einer degradierten
Seite, die ein langes $args zurückgibt, und Worker-SIGSEGV/Respawn-Stürme.