Skip to content

Latest commit

 

History

1 Commit

Folders and files

Repository files navigation

php2shell-poc

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.

Tools

php2shell_oom_check.py — non-destructive reachability check

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.

resolve_zif.py — offset resolver for stripped builds

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).

SAPI note (matters for triage)

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.

Remediation

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.

License

Apache-2.0.

Releases

Packages

Contributors

Languages