PHP2Shell: what 884,000 unpatched hosts mean for the PHP runtime you already forgot you were running
On 21 October 2026 the PHP project released fixes for CVE-2026-109618 and CVE-2026-109619, two remote code execution flaws each rated 9.2 under CVSS v4.0. The fixed releases are PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35. Older branches were outside normal upstream support, though the project provided minimal source backports for 7.4, 8.0 and 8.1.
The reason this deserves attention out of proportion to a normal patch release is where the flaw executes. Both vulnerabilities are in the PHP runtime itself, and exploitation completes before the request reaches application code. Every mitigation that lives inside a framework, a middleware chain, a WAF rule set tuned to application paths, or a maintenance-mode switch is irrelevant to the vulnerable parsing step.
The mechanism
CVE-2026-109618 concerns how PHP unwinds from out-of-memory conditions. PHP uses longjmp() to abort the current context when a memory allocation fails. NVD's description is precise: some contexts do not account for that scenario properly and leave request memory uninitialized before performing an allocation, and the subsequent cleanup procedure may read or branch on that memory. Multiple out-of-memory strategies trigger this condition reliably, which is why the vendor does not treat it as a narrow race.
CVE-2026-109619 concerns global state that temporarily points into request memory. In some scenarios the global state is not correctly reset, or is repopulated after being reset, and later requests on the same worker read or branch on stale pointers into freed memory.
Both end in remote code execution. Independent researchers reproduced them and confirmed that application-level authentication cannot block the attack, because the malicious request is processed before any application code runs.
A third consequence is less discussed and operationally significant: worker memory disclosure. Datawatch's analysis reports demonstrated unauthenticated disclosure of PHP worker memory, which can contain passwords, session tokens and API keys. In a shared worker pool this turns an information leak into a credential compromise across tenants of the same runtime.
Inventory is the hard part
The unit of patching here is not the application. It is every PHP runtime that serves HTTP requests, including Apache mod_php, PHP-FPM, php-cgi, FrankenPHP and LiteSpeed. Containers and appliances that bundle their own interpreter count, and a container that has never been rebuilt since deployment is still running whatever version it shipped with.
The inventory questions that actually matter:
Which images in the registry contain a PHP base layer, and what version does each one carry?
Which vendor appliances or packaged applications embed PHP and are updated only through the vendor?
Which hosts run PHP 8.1 or earlier, where the fix comes from a distribution backport rather than upstream?
Orca's analysis estimates roughly 884,000 internet-facing hosts still running PHP 8.1 or older, representing about 59 percent of the ~1.5 million hosts that report a version, with another 740,000 reporting PHP without a version number. Those figures come from a vendor's internet-wide telemetry and describe reported versions, not verified vulnerability. They are useful as an argument for how much end-of-life PHP faces the internet, and not as a count of exploitable systems.
Applying the fix correctly
Three steps are routinely skipped.
First, restart or replace the workers. A rolling restart that leaves old FPM processes serving traffic leaves the vulnerable runtime in place, and a deployment system that reports success after replacing files has not necessarily replaced processes.
Second, rebuild images rather than patching inside them. A container where someone ran a package upgrade in place diverges from its build definition the moment it restarts from the original image.
Third, check vendor package versions rather than upstream numbers. Distribution backports frequently keep the upstream version string and add a revision suffix, so a host reporting 8.2.x may or may not be fixed. The vendor advisory is the authority.
Interim controls and their honest limits
PHP's own guidance distinguishes the two vulnerabilities.
For CVE-2026-109618, the temporary measures involve preventing the out-of-memory condition from being reached: enforce a memory limit at the administrator level, cap decoded request body sizes including requests that omit a usable Content-Length header, and apply memory limits at the container boundary. PHP specifically warns against substituting process-level limits such as RLIMIT_AS or RLIMIT_DATA, because those can trigger the very allocation failures the vulnerability depends on.
For CVE-2026-109619, community advice has centred on disabling session.upload_progress.enabled. Datawatch's testing contradicts that as a complete fix, and NVD's description mentions multiple strategies reaching the same stale-state condition. Treat the setting as a reduction in one path rather than a resolution.
Boundary controls behave differently. A reverse proxy or load balancer in front of PHP that rejects oversized or malformed request bodies blocks the request before it reaches the vulnerable parser, which is a genuine reduction in reachable surface. It does not change the installed version, and it stops working the day someone routes around the proxy for a debugging session.
CERT-EU's advisory 2026-018 recommends isolating internet-facing PHP applications behind a VPN or WAF where immediate patching is impossible.
Detection notes
Cloudflare reported attack traffic targeting these vulnerabilities within hours of release, including attempts to evade its protections. That establishes interest, not successful exploitation.
Detection guidance from vendors converges on three observations: large form submissions or multipart bodies followed by memory-exhaustion errors during request initialization; worker processes spawning unexpected shells; and, for the disclosure path, responses that leak memory fragments into output or headers.
The middle item is the highest-signal of the three, because a PHP worker has no legitimate reason to start a shell. It is also the one most likely to be already monitored, which is useful given how little time there was between disclosure and attempted exploitation.
References
PHP security release, 21 October 2026, and the accompanying foundation statement
NVD entries for CVE-2026-109618 and CVE-2026-109619
Datawatch Security Labs, "PHP2Shell - Critical vulnerabilities in PHP", 21 October 2026
Unit 42 threat brief on CVE-2026-109618 and CVE-2026-109619
Orca Security, PHP2Shell analysis, including the end-of-life host estimate
Qualys, "PHP2Shell: PHP Patches Two Critical RCE Vulnerabilities", updated 21 October 2026
CERT-EU advisory 2026-018