> “Building the exploit required chaining multiple flaws and adapting to each target’s memory layout through repeated testing and debugging.”
> — [Wiz Research](
| Advisory | Lab setup and request | Result observed here |
| [CVE-2026-109618]( | PHP 8.4.26 with Apache `mod_php`, `memory_limit=16M`, and `post_max_size=8M`. The runner sends one multipart part with 80,000 headers ( 6.56 MB on the wire). | PHP reports that it exhausted the memory limit while parsing. Apache answers a follow-up health check. This demonstrates the OOM trigger, not the later cleanup corruption, a memory disclosure, or RCE. |
| [CVE-2026-109619]( | PHP 8.5.4 with Apache prefork limited to one worker and `fatal_error_backtraces=1`. One request raises a fatal error; the applies `auto_detect_line_endings=1` from `.htaccess`. | The consumer connection closes, Apache logs `zend_mm_heap corrupted`, and the health check reaches a replacement worker. In the control run, `fatal_error_backtraces=0` and all requests complete on the same worker. This demonstrates a worker abort on this setup, not a controlled use-after-free or RCE. |
Both PHP versions are in the affected ranges listed in the advisories. The
patched releases are PHP 8.2.35, 8.3.36, 8.4.27, and 8.5.12.
You need Docker Engine with the Docker Compose plugin and network access the
first time the images are pulled. From this directory, run:
Compose builds the lab images, runs both trigger cases and the control, then
prints the request results with the Apache/PHP logs. The containers publish no
host ports. Each target and its runner use a separate internal Docker network.
Press Ctrl+C after the results appear, then remove the containers and networks
The Compose file uses the host's native Linux architecture; it does not force
`linux/amd64`. The official PHP images provide both AMD64 and ARM64 variants,
so Apple Silicon users do not need AMD64 emulation for this lab. Both trigger
cases and the control were observed on this machine using native ARM64 images
and, separately, AMD64 images under Docker emulation, with the same results.
That only establishes that these trigger checks ran on both architectures.
Memory layout and allocator behavior can still differ across architectures,
builds, and configurations. This lab does not attempt the heap shaping needed
The runners are wired to the disposable targets created by this Compose file;
they do not accept an arbitrary container or URL. The first case needs the
PHP 8.4.26 Apache image and the memory settings above. The second needs the PHP
8.5.4 Apache image, `fatal_error_backtraces=1`, one persistent prefork worker,
and the producer and consumer endpoints included in this repository. The lab
also enables PHP error display/logging and sends PHP and Apache diagnostics to
the container logs. FPM, FrankenPHP, CGI, and unrelated Docker containers are
The CVE-2026-109618 runner builds a bounded multipart body with 80,000 part
headers and sends it to the PHP 8.4.26 target. The request is below the target's
`post_max_size`, but parsing its headers exceeds PHP's 16 MB `memory_limit`.
The runner then checks whether Apache still answers. Its own container has
separate memory, CPU, and process limits.
The CVE-2026-109619 runner first calls the fatal-error producer, then the
consumer endpoint whose `.htaccess` applies the per-directory INI setting.
Each endpoint returns its worker PID. Apache is configured with one prefork
worker, so the control should report the same PID for each request. In the
vulnerable run, the follow-up health check should report a new PID after
Apache replaces the worker that aborted. The control changes only
- Neither case demonstrates remote code execution, arbitrary command
execution, or a controlled memory primitive.
- The CVE-2026-109618 case reaches OOM during multipart parsing. It does not
demonstrate the cleanup corruption or upload-progress unserializer path
described in the exploit research, and it does not disclose process memory.
- The CVE-2026-109619 case records a worker abort after a producer/consumer
sequence. It does not prove control of the stale pointer or exercise the
- Both cases use Apache `mod_php`; they do not test FPM, FrankenPHP, CGI, or
- The `fatal_error_backtraces=0` control is a configuration comparison, not a
- PHP image tags and their underlying system packages may change over time.
These runs used Docker Engine 29.7.2 and Docker Compose 5.4.0; later image
rebuilds may use different system package revisions.
For production systems, install a vendor-supported PHP release containing the
fixes. Updating is the only complete mitigation described in the PHP release
- [PHP security release notice (21 October 2026)](
- [Wiz Research: PHP2Shell technical write-up](
- [GHSA-w8hw-w9fx-j79w / CVE-2026-109618](
- [GHSA-6wmf-4rv5-p3rp / CVE-2026-109619](
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.
