Skip to content

Back to the catalog

PHP2Shell - Critical vulnerabilities in PHP (CVE-2026-109618, CVE-2026-109619): detection, analysis, and remediation
securitylabs.datadoghq.comwriteup

PHP2Shell - Critical vulnerabilities in PHP (CVE-2026-109618, CVE-2026-109619): detection, analysis, and remediation

PHP2Shell is Datadog Security Labs' analysis of two critical PHP RCE flaws, CVE-2026-109618 and CVE-2026-109619 (CVSS v4.0 9.2), disclosed 21 October 2026. It walks through a reproduced exploit on PHP 8.5.11 (heap grooming, a fake array, and a destructor calling system()) and the stale-state use-after-free. It lists fixed versions (8.2.35, 8.3.36, 8.4.27, 8.5.12), partial mitigations, and detection signals across requests, error logs and shell child processes.

TL;DR Explains how the PHP memory-exhaustion and stale-state RCE bugs work, how to patch them, and how to detect exploitation.
Document

What it is

Datadog Security Labs' write-up of CVE-2026-109618 and CVE-2026-109619, two PHP remote code execution flaws (CVSS v4.0 9.2 each) disclosed 21 October 2026. Datadog reproduced the first on PHP 8.5.11. AWS reported exploitation attempts from 17 October 2026, four days before disclosure, and Datadog reports multiple in-the-wild exploitation reports and broad scanning as of 21 October.

How it works

Both flaws share a pattern: a fatal error interrupts an operation, and PHP later treats the incomplete state as valid.

  • CVE-2026-109618: _zend_hash_str_add_or_update_i() increments nNumUsed and nNumOfElements before it allocates the key. If the key allocation exceeds memory_limit, the counted bucket is never initialized. At shutdown PHP destroys $_POST, reads stale heap bytes as a PHP value, follows it into an attacker-built fake array, and calls its destructor callback, set to system().
  • CVE-2026-109619: worker-wide fields keep pointers to freed per-request memory. Two confirmed cases: fatal-error backtraces (PHP 8.5 only, command execution on mod_php) and upload processing (mod_php and PHP-FPM). The upload case uses session upload progress, which is on by default and runs even if the app never calls session_start().

The failure happens during request initialization, so application authentication and filtering cannot stop it. In the lab exploit the worker returned HTTP 200 and kept running, so neither a crash nor an error status is a reliable signal.

Preconditions / Affected

Any PHP runtime serving HTTP: Apache module, PHP-FPM, php-cgi, FrankenPHP, LiteSpeed. Default memory limits are vulnerable. Branches 7.4, 8.0 and 8.1 are affected, and the PHP security team published source backports for them. Bundled interpreters in containers can differ from the CLI PHP version. CVE-2026-109619 needs the attacker's requests to reach the same worker, and a larger pool lowers the success rate per attempt. Defeating ASLR is a separate step, and the PHPSESSID cookie memory leak (described by Wiz) can supply addresses.

What to do

Patch to 8.2.35, 8.3.36, 8.4.27 or 8.5.12, or to a vendor package (vendors may backport without changing the version number). Rebuild and redeploy container images, then restart or replace every worker. For 8.1 and older, check vendor coverage or move to a supported branch.

If you cannot patch yet, PHP's temporary guidance is:

  • CVE-2026-109618: set memory_limit=-1 at administrator level, with frontend request limits and container memory limits. Cap decoded body size, including requests without a usable Content-Length. Do not use RLIMIT_AS or RLIMIT_DATA, which can trigger the allocation failures.
  • CVE-2026-109619: set session.upload_progress.enabled=0 and, on PHP 8.5, fatal_error_backtraces=0. Load both before request parsing and restart all workers.
  • Restrict public access, and block requests at a reverse proxy or other boundary in front of PHP (CERT-EU advice).

Detection signals:

  • Requests: multipart POSTs with PHPSESSID and PHP_SESSION_UPLOAD_PROGRESS fields, hundreds of parts (about 900 fit under 1 MB), deeply nested names like files[R00001][a][a][a], fill fields of 100 MB or more, upload filenames containing <?php or |O:, and urlencoded bodies with a single field name of 3 to 60 MB plus null bytes. Also watch for uploads that stall and for bursts of slow connections. Track parts per request and nesting depth, since body size alone is weak.
  • Responses: Set-Cookie: PHPSESSID= with a long, percent-encoded or binary value, which suggests heap disclosure.
  • Logs: Allowed memory size ... exhausted ... in Unknown on line 0 (failure before any script ran) and Apache AH00052 ... Segmentation fault (11). A full attack can produce only two to four memory errors, then go quiet.
  • Processes: any shell spawned by a web worker, such as apache2 (www-data) to sh -c.
  • CVE-2026-109619: early configuration warnings, shutdown diagnostics, fatal errors and timeouts on reachable routes.

Check that your WAF actually inspects truncated, chunked or unenumerated parts.

Caveats

  • Every mitigation is partial. memory_limit=-1 blocks the known path only, and allocation failures can still occur and destabilize the host. Hiding errors does not prevent stale-state access. Patching is the only complete fix.
  • The 8.5.12 patch defers memory errors to a safe point and uses _exit(137) past a hard limit. The insertion code still updates counters before allocating the key. Datadog expects more bugs of this pattern and unpatched variants in older branches.
  • Public PoCs hit other code paths with the same flaw, so do not tune detections to the hash-table specifics or to the lab's command names.
  • The reproduction used a single worker, no OPcache and visible errors. Datadog's detections (Workload Protection, two Cloud SIEM rules) cover shell execution only.

Organisations named here

  • ASLR
  • CERT-EU
  • heap grooming
  • PHPSESSID memory disclosure

CVEs named here

  • CVE-2026-109618
  • CVE-2026-109619

Technologies named here

  • Datadog Cloud SIEM
  • php-cgi
  • Wiz
  • FrankenPHP
  • LiteSpeed
  • AWS
  • PHP 8.5
  • PHP
  • Apache
  • CVSS
  • Apache modules (mod_php)
  • CERT-EU
  • Datadog Cloud Vulnerability Management
  • Datadog Workload Protection
  • PHP 8.1 and earlier (outside normal upstream support; source backports provided for PHP 7.4, 8.0 and 8.1)
  • PHP 8.5.11 (tested version, built from commit 678778973bb4d4185c06ef1320de50f1a975d3c8, on Debian 12 ARM64 with Apache prefork and mod_php)
  • PHP FastCGI Process Manager (PHP-FPM)
  • Web application firewall (WAF) / reverse proxy

Techniques named here

  • Use-after-free
  • Destructor callback hijacking
  • Detection of memory exhaustion errors
  • Detection of suspicious form submissions
  • Detection of unexpected shell processes
  • Heap grooming
  • Memory disclosure via PHPSESSID cookie
  • Response header inspection
  • Use-after-free via stale state across requests (CVE-2026-109619)

Threat actors named here

  • PHP2Shell