Update root README with current UAF RCE exploit details

Replaced outdated BG(serialize) description with the current three-stage
exploit chain: heap leak, code leak, and RCE via fake HashTable with
pDestructor=zif_system. Updated usage examples, test results (5/5 RCE on
PHP 8.4.26, 8.3.35, and WordPress 6.8.1), and chunked TE bypass details.
Fixed script filename reference (rce_exploit.py).
This commit is contained in:
neko
2026-10-23 03:52:12 +00:00
parent ac4e654dd6
commit 32e5d9c8fa
+36 -19
View File
@@ -34,7 +34,7 @@ against `cleanup=1`, the poisoned session file is includable via LFI for RCE.
| `bypass/waf_bypass_test.py` | WAF rules | Tests Content-Type evasion against WAF rules |
| `nolfi/exploit_nolfi.py` | No LFI available | Served save_path + fpm pathinfo — **RCE with no application include** |
| `fcgi/exploit_fcgi.py` | FPM reachable | FastCGI slow-drip + auto_prepend_file — **RCE, default config, no LFI** |
| `uaf-rce/exploit.py` | Apache mod_php | OOM → UAF via stale BG(serialize) → heap spray → **RCE, no LFI, no framework** |
| `uaf-rce/rce_exploit.py` | Apache mod_php | OOM → dangling PS(id) → heap spray → full ASLR bypass → **RCE, no LFI, no framework** |
## Prerequisites
@@ -160,32 +160,49 @@ pool-level configuration can prevent this when FastCGI is reachable.
## UAF RCE (Apache mod_php, No LFI, No Framework)
`uaf-rce/exploit.py` exploits the same CVEs through a pure memory corruption
path that requires **no LFI, no framework, no libraries, and no non-default
PHP settings**. The only SAPI requirement is Apache mod_php with prefork MPM
(default on Debian/Ubuntu).
`uaf-rce/rce_exploit.py` exploits the same CVEs through a pure memory
corruption path that requires **no LFI, no framework, no libraries, and no
non-default PHP settings**. The only SAPI requirement is Apache mod_php with
prefork MPM (default on Debian/Ubuntu).
The attack triggers an OOM during multipart parsing to leave stale
`BG(serialize)` state in the surviving Apache prefork worker. On the next
request, the session upload progress handler reuses the stale pointer (a freed
64-byte ZendMM slot) as a `php_serialize_data` struct. Heap spray reclaims the
slot with attacker data shaped as a fake `HashTable`, giving control of
`pDestructor` for arbitrary function call.
Three-stage exploit chain with full ASLR bypass, all over plain HTTP:
1. **Heap leak**: OOM during multipart parsing leaves a dangling `PS(id)`
pointer. A second request sprays a fake `zend_string` with `len=0x1000`
over the freed slot. `php_session_send_cookie` reads 4096 bytes of heap
data into a `Set-Cookie` header, revealing the Zend MM chunk base.
2. **Code leak**: Same mechanism, but the spray places a real `HashTable`
at the target slot. The `pDestructor` field leaks the libphp.so base.
3. **RCE**: A fake `HashTable` with `pDestructor = zif_system` and an
embedded command string is sprayed onto the heap. Session cleanup calls
`zend_hash_destroy` on the fake table, invoking `system(cmd)`.
The `post_max_size` limit is bypassed via chunked `Transfer-Encoding`:
PHP only checks `Content-Length`, so a chunked request with no
`Content-Length` header delivers the full OOM payload (140MB) despite the
default 8MB limit.
Tested: 5/5 first-attempt RCE on `php:8.4.26-apache`, `php:8.3.35-apache`,
and WordPress 6.8.1 on stock PHP, all with zero configuration changes.
```bash
# Confirm all primitives (OOM, worker survival, session poison, stale state)
python3 uaf-rce/exploit.py --target http://host:port/index.php --oom-only
# Auto-detect PHP version, look up offsets, exploit
python3 uaf-rce/rce_exploit.py -u http://target/index.php
# Full chain: OOM + heap spray + UAF trigger
python3 uaf-rce/exploit.py --target http://host:port/index.php
# Verify RCE via docker exec
python3 uaf-rce/rce_exploit.py -u http://target/ \
--docker-proof CONTAINER /tmp/pwn
# With crash detection
python3 uaf-rce/exploit.py --target http://host:port/index.php --crash-test
# Multi-worker Apache
python3 uaf-rce/rce_exploit.py -u http://target/ --workers 150
# Custom command (max 14 bytes; use 'sh</tmp/c' for longer)
python3 uaf-rce/rce_exploit.py -u http://target/ -c 'id>/tmp/pwn'
```
PHP-FPM is not vulnerable: workers exit on bailout (code 70), so stale state
never persists across requests. See `uaf-rce/FINDINGS.md` for the full
vulnerability analysis and patch details.
never persists across requests. See `uaf-rce/README.md` for the full
vulnerability analysis, patch details, and offset database.
## Patch Bypass Findings