Detection and offset tooling for PHP2Shell — CVE-2026-109618 (OOM / uninitialised-pointer) and CVE-2026-109619 (stale global state / UAF), unauthenticated RCE in the PHP runtime. Affects PHP 5.4.0–8.5.11; fixed in 8.2.35 / 8.3.36 / 8.4.27 / 8.5.12.
OffSeq Cybersecurity · authorized testing only.
Sends a chunked multipart request with amplified duplicate part-headers
(bypasses post_max_size, ~50× heap amplification) and reports whether the
pre-RINIT OOM bailout is reachable. No code execution.
python3 php2shell_oom_check.py -u https://host/index.php
python3 php2shell_oom_check.py -u https://host/app.php --json --ct-bypass
Verdicts: TRIGGER_REACHABLE (high = in-band OOM text; medium = worker-abort
differential) · NO_SIGNAL · INCONCLUSIVE · UNREACHABLE.
Recovers unsymboled zif_* handler offsets (e.g. zif_system) from a PIE via
its zend_function_entry relocations — needed when a php-fpm binary lacks them.
python3 resolve_zif.py /path/to/php-fpm system shell_exec
profiles/ holds measured per-build offset sets (apache + fpm, 8.4.24 amd64).
The 109618 disclosure/RCE chain needs the arming OOM to leave PS(id) dangling
in a worker that survives the fatal, so a second request can reclaim it.
- Apache mod_php (prefork): child survives the OOM → RCE-exposed.
- php-fpm: worker terminates on the OOM → the dangling state dies with it → this vector is DoS-only. FPM code execution requires the separate CVE-2026-109619 upload-progress UAF.
So TRIGGER_REACHABLE = RCE-exposed on mod_php, OOM-DoS on fpm.
Patch the PHP runtime (8.2.35 / 8.3.36 / 8.4.27 / 8.5.12). No CMS/plugin update fixes this. Mitigations are partial; patch.
Apache-2.0.