Skip to content
Exploit for Improperly Controlled Sequential Memory Allocation in Php

Exploit for Improperly Controlled Sequential Memory Allocation in Php

Sploitus • October 22, 2026

A clean-room rewrite of the php2shell exploit for the two critical PHP core vulnerabilities disclosed on 21 October 2026. This is not a new vulnerability — the bugs are the same as in the original proof-of-concept by godylockz. What is new: the code has been rewritten for readability and understandability so that defenders can follow the exploit chain without needing C-level memory layout knowledge.

The exploit delivers an unauthenticated one-shot remote code execution against any PHP installation with `session.upload_progress` enabled. It chains four stages over plain HTTP:

1. **Worker rotation** — trigger an OOM crash in the prefork worker, forcing a new process to spawn with the same address space layout

2. **Heap leak** — leak heap chunk addresses via a corrupted PHPSESSID cookie

3. **libphp leak** — leak the libphp base address (including the `zif_system` function pointer)

4. **RCE** — forge a destructor call that routes into `system()`, executing the command

The target needs only a minimal PHP page (``) and `session.upload_progress.enabled = 1` (the default). No authentication, no custom application code, no target-side files to upload.

| Readability | Compact, minimal | Sectioned, inline docstrings, named constants |

| Variable names | Shortened / golfed | Descriptive (`heap_base`, `libphp_base`, `stage3_pads`) |

| Flow | Linear script with functions | Class-based `ExploitRunner` with stage methods |

| | C-level struct offsets | Plain-English explanation of each step |

| Structure | One file, everything on one plane | Organized sections with headers and docstrings |

Check if a target is likely vulnerable without sending exploit traffic:

python3 php2shell-refactored.py check -u

python3 php2shell-refactored.py check -f targets.txt -o results.jsonl

[VULNERABLE] PHP 8.4.26

[PATCHED] PHP 8.4.27

Requires Apache mod_php prefork on Linux. Works against the Docker lab or any matching real target.

docker compose -f docker/docker-compose.yml up -d

# Run (auto-derives libphp offsets from the container ELF)

python3 php2shell-refactored.py exploit -u

[*] reading libphp offsets from container php2shell-target

[*] target

- `-f FILE` — target list file (one URL per line, `#` allowed)

- `--workers N` — parallel workers (default: 4)

- `--timeout SECS` — HTTP timeout (default: 10)

- `--json` — machine-readable JSON output

- `-c CMD` — command to execute (default: `id;hostname -I;hostname`)

- `-o FILE` — write exploit output to file

- `--profile PROFILE` — calibration profile: `workbook` (Debian 12 / Apache 2.4.69) or `lab` (Apache 2.4.68)

- `--zif-offset 0x...` — override zif offset inside libphp

- `--dtor-offset 0x...` — override destructor offset inside libphp

- `--htdata-offset 0x...` — override htdata offset

- `--container NAME` — Docker container name for automatic offset detection

- `--offsets-file PATH` — pre-loaded offsets (hex or decimal values, key=value)

- `--force` — override platform check (e.g. nginx)

- `--no-preflight` — skip the preflight GET that checks the Server header

- `--timeout SECS` — HTTP timeout (default: 30)

The exploit first forces the PHP prefork worker to crash via an out-of-memory condition. When the worker respawns, it inherits the same address space layout. This is the key to the whole attack — the leaked pointers from stages 1 and 2 remain valid because the new worker has the same memory layout as the old one.

This only works with Apache mod_php prefork on Linux because it relies on `fork()` (copy-on-write). Windows Apache builds don't use `fork()`; they use thread pools, which randomize memory on every spawn.

With the worker in a corrupted state, the exploit sends a crafted multipart POST that triggers an out-of-bounds read in PHP's session cookie handling. The read leaks heap chunk addresses into the `Set-Cookie` header. By analyzing the leaked cookie data, the exploit identifies the base of the Zend memory manager — the heap region where PHP stores its data structures.

Using the heap base from stage 1, the exploit sends another crafted request that places a corrupted pointer into the session state. A follow-up read leaks a pointer into libphp.so — specifically, the `pDestructor` function pointer that PHP uses to clean up hash tables. Since `pDestructor = libphp_base + dtor_offset`, the exploit can compute the base address of libphp.so.

This is critical because the base address lets the exploit compute the address of `zif_system`, the PHP internal function that executes shell commands.

With the libphp base known, the exploit constructs a forged HashTable in memory that tells PHP to call `system(command)` when it "deletes" the hash table. The exploit sends a final multipart POST that triggers this chain:

`session handler` -> `zval_ptr_dtor` -> `zend_array_destroy` -> `pDestructor(command)` -> `system("sh</out/c")`

The command is embedded directly in the forged structure. Commands longer than 14 bytes are written to `out/c` and executed via `sh</out/c` (a standard trick to bypass the size limit).

- Stage 0 requires `fork()` for copy-on-write worker rotation

- Offsets (`zif_offset`, `dtor_offset`, `htdata_offset`) index `libphp.so` (ELF format)

- The `system("sh</out/c")` payload is POSIX

The two underlying bugs exist in the C code that PHP compiles for all platforms, so Windows PHP builds are vulnerable in principle. But the exploit would need retuning of offsets and a different crash-survival mechanism to work on Windows.

ASLR is not a barrier — the `Set-Cookie` out-of-bounds read in stage 2 leaks the heap and libphp base addresses directly, so full ASLR/PIE is read off the wire.

All PHP versions with `session.upload_progress` enabled (introduced in 5.4.0):

curl -sI | grep X-Powered-By

Update PHP to the fixed version and restart all workers:

### Mitigate (if patching is not immediately possible)

For CVE-2026-109618 specifically, lowering `post_max_size` and raising `memory_limit` reduces the OOM surface:

Watch Apache/FPM error logs for unexpected child crashes (SIGABRT, SIGSEGV) during normal traffic. Unusual multipart POST requests containing `PHP_SESSION_UPLOAD_PROGRESS` fields to endpoints that do not expect file uploads are suspicious.

| `php2shell-refactored.py` | Refactored exploit (this rewrite) |

| `docker/docker-compose.yml` | Vulnerable target container |

| `docker/apache.conf` | Single-worker prefork config |

| `docker/offsets.py` | Auto-read libphp offsets from container ELF |

| `docker/www/index.php` | Minimal target page |

| `out/` | Proof output and offset cache |

- [PHP security advisory 2026-10-21](

- [GHSA-w8hw-w9fx-j79w]( — CVE-2026-109618

- [GHSA-6wmf-4rv5-p3rp]( — CVE-2026-109619

- [Patch commit 3584a98](

- [Sansec analysis](

- [Original POC by godylockz](

Use this only against systems you own or are authorized to test. The exploit has been tested against the Docker lab (Apache 2.4.68-69, Debian 12, PHP 8.4.x) and may not work unmodified against real-world targets with different compile-time options, ASLR configurations, or kernel parameters. Commands longer than 14 bytes require writing to `out/c`.

Extracted Entities