Skip to content

php2shell verification v1.0.0 (2026-10-24)

Choose a tag to compare

@JoshRob297 JoshRob297 released this 24 Oct 23:23
· 22 commits to main since this release

php2shell verification report — v1.0.0 (2026-10-24)

Independent verification of CVE-2026-109618 / CVE-2026-109619 and the follow-up advisory
CVE-2026-115560. Lab-only: official PHP images, loopback traffic, disposable containers. No
production system was touched.

TL;DR

  • Pre-auth RCE reproduced in the lab: 3/3 with display_errors=On + ASLR on; 3/3 with
    display_errors=Off + ASLR off (lab 8M override). 8.4.27 control: 0/5.
  • The forged-cookie channel discloses heap, not the session table. 47 Zend MM bin-64
    free-list pointers reveal the id chunk base; the session HashTable is never in the window.
    The leak narrows libphp to a 1.88 MB window (~481 pages) with a fixed page offset; it does
    not pin ASLR.
  • The Off + ASLR-on route is closed by both tested mechanisms. The leak does not exist on
    FPM (payload A exits the worker), and on mod_php the leak's OOM clears the stale
    BG(unserialize) state that chain E needs.
  • post_max_size is not enforced on chunked bodies on unpatched branches (8.2.34, 8.3.35,
    8.4.26 mod_php): a chunked 30 MB multipart parses in full and a chunked 70 MB multipart
    OOMs at defaults. 8.4.27/8.5.12 reject chunked bodies over the limit; FPM does not parse
    chunked bodies; nginx body caps apply.
  • Chain D (stale EG + forged zend_object spray): the OOM precondition is confirmed, but
    EG(objects_store), vm_stack and current_execute_data are identical at
    php_request_shutdown before and after the OOM. The stale-EG step is not supported by our
    measurements; only the OOM precondition is.
  • CVE-2026-115560: condition reproduced (php_binary config + runtime ini_set() to php
    before session_start()) as a decode failure without a memory-safety symptom. Inconclusive
    until the full advisory is public.

What changed in this revision

  1. Corrected the "no leak" claim: the forged cookie does disclose heap; what it never
    discloses is the session HashTable.
  2. Corrected the "default limits stop the primitive" boundary: true for Content-Length bodies
    and the published payload sizes; chunked bodies bypass post_max_size on unpatched
    mod_php, and the 8.4.27/8.5.12 patch closes that route.
  3. Added the closure of the Off + ASLR-on route (FPM negative + leak/E-OOM exclusivity), the
    chain D EG measurement and the bounded 115560 attempt.
  4. Added CVE-2026-115560 to the disclosure timeline and remediation guidance.

Contents

File Contents
REPORT.md Full technical report
RESUMEN.md Executive summary (ES)
EVIDENCE.md Sanitized lab evidence and matrices (sections 1-12)
validation/ PS(id) vs HashTable matrix and conclusions
detection/ Additive Suricata and Sigma rules
tooling/ oom_reach.py, forged_cookie_check.py, labkit/
raw/ Redacted raw lab captures
POCS.md, COVERAGE.md, METHODOLOGY.md, REMEDIATION.md, FAQ.md, REFERENCES.md Supporting documents

Defensive guidance

  • Patch to 8.4.27 / 8.3.36 / 8.2.35 / 8.5.12.
  • Keep stock resource limits; cap request bodies at the proxy (nginx client_max_body_size
    applies to chunked requests; Apache LimitRequestBody defaults to unlimited).
  • session.use_strict_mode=1, session.use_only_cookies=1; disable session.upload_progress
    if unused. For CVE-2026-115560, session.upload_progress.enabled=0 until the next regular
    release.
  • Deploy the detection rules in detection/ (forged-cookie, groom signatures, abort bursts).

Assets

  • php2shell-REPORT.pdf — technical report (EN)
  • php2shell-RESUMEN.pdf — executive summary (ES)
  • SHA256SUMS — checksums of the assets

Scope and responsible use

This material is for defensive research, patch verification and controlled testing. No exploit
code is redistributed; public PoCs are reviewed by URL in POCS.md. Do not use the described
techniques against systems you do not own or have explicit authorization to test. For
vulnerabilities in PHP itself, follow the PHP project security process.