• 10 min read

PHP2Shell makes PHP asset inventory an incident-response task

Two unauthenticated PHP RCE flaws have working attack paths before application code runs. Patching is necessary, but finding embedded PHP is urgent.

PHP2Shell makes PHP asset inventory an incident-response task

Image: BleepingComputer

Two flaws collectively called PHP2Shell make PHP discovery an incident-response task, not routine maintenance. CVE-2026-109618 and CVE-2026-109619 can give an unauthenticated attacker remote code execution with the privileges of the web worker. They affect PHP installations serving web requests through Apache mod_php, PHP-FPM, php-cgi, FrankenPHP, and LiteSpeed.

The PHP project issued emergency releases on October 21, 2026: PHP 8.5.12, 8.4.27, 8.3.36, and 8.2.35. The bugs have a 9.2 CVSS score and affect web-facing PHP deployments reaching back to PHP 5, though the project supports only PHP 8.2 and later. PHP 7.4, 8.0, and 8.1 have minimal source backports for organizations that must build from source or lack a vendor-provided long-term-support fix.

The immediate risk is not confined to a CMS, framework, or custom application route. At least one demonstrated path runs during PHP request startup, before application code executes. A site is not safe simply because developers have constrained application-level upload handling or authentication flow.

SiteGuard’s statistics feature makes WAF patching an incident-response task

Recommended reading

SiteGuard’s statistics feature makes WAF patching an incident-response task

Sergey Kuznetsov • • 4 min read

“There are no complete mitigations, updating is the only safe choice.”

— PHP Foundation

The official CVE-2026-109618 advisory says configuration changes can reduce known attack paths but do not eliminate the vulnerable behavior. Internet-facing servers should be patched. Teams also need to identify appliances, hosting panels, vendor products, and old applications that bundle PHP without making it visible in the application inventory.

Two bugs, two ways to cross a request boundary

The shared outcome—unauthenticated code execution—comes from two different failure modes. CVE-2026-109618 is an out-of-memory handling problem. PHP uses longjmp() to exit request processing after an OOM condition. In certain early request contexts, it can exit while request memory is only partly initialized. The shutdown procedure can then read or branch on invalid state.

The confirmed attack uses multipart parsing techniques to consume more memory than the request appears to require. A malformed or unhelpful declared content length can get past the initial post_max_size check. Unlimited multipart headers can expand dramatically in PHP’s internal representation; empty file controls still create metadata arrays without counting toward max_file_uploads; and nested field names multiply array work. The failed allocation itself does not need to be associated with the invalid memory that later reaches shutdown.

CVE-2026-109619 is a stale-state use-after-free across requests handled by the same persistent worker. PHP retains global error, session, object, and extension state in workers, but some of that state can point to memory owned by the prior request. A fatal error, execution timeout, OOM event, or later nonfatal diagnostic can leave that state published after the request heap is freed. A subsequent request can consume it before ordinary request initialization resets it.

VulnerabilityCore defectConfirmed execution pathImportant deployment distinction
CVE-2026-109618OOM-triggered early exit leaves request state invalidUnauthenticated RCE over HTTP against Apache mod_phpFPM is considered susceptible from source analysis, but this SAPI did not have a complete demonstrated exploit for this specific path
CVE-2026-109619Persistent worker state points to freed request memoryHeap use-after-free, memory disclosure, and RCE as the web workerRCE was confirmed with mod_php; the session-lifecycle path was also validated with FPM

For CVE-2026-109618, Apache mod_php is the clearest danger because it unconditionally runs request shutdown even when startup fails. The advisory says this enables the issue before application-specific code begins. FrankenPHP is likely exposed for a similar reason. FPM behaves differently when startup fails: it exits the child process, so the invalid state is not consumed in that sequence. That reduces risk in one path; it is not an exemption from the flaw.

For CVE-2026-109619, the worker lifecycle is the central condition. The producing request must leave state behind, and a later consumer request must land on the same worker before normal initialization clears it. The advisory’s strongest demonstrated case on PHP 8.5 uses fatal_error_backtraces. Another confirmed route uses session upload progress, which is enabled by default and does not require the application to call session_start(). The latter was validated against both mod_php and a normal dynamic FPM pool, though the FPM case requires a suitable application operation after startup.

Every PHP server is not identically exploitable, according to the technical advisories. Nor is an FPM deployment safe. Exploitability differs by SAPI, build, allocator layout, extensions, frontend behavior, and application paths, but affected software still requires remediation.

Fixed branches and legacy systems

The PHP project’s supported branches have fixed releases. Deployments on older branches face a more awkward decision: use a distribution or long-term-support vendor backport, build the project’s minimal backport, or migrate to a supported release. A server running PHP 8.1 or earlier does not become safe merely because the upstream project no longer publishes ordinary maintenance updates for it.

PHP branchRelease or remediation status
PHP 8.5Update to 8.5.12
PHP 8.4Update to 8.4.27
PHP 8.3Update to 8.3.36
PHP 8.2Update to 8.2.35
PHP 8.1 and olderUpgrade, use an LTS vendor fix, or use the available minimal source backport where applicable

The October 21 fixes followed an advance warning on October 20, 2026. The project told administrators to prepare for a critical update and said it could release sooner if details became public or exploitation appeared. The warning gave teams time to locate packages and schedule downtime, but organizations knew they had a severe web-layer problem before the full technical details were available.

DateWhat happened
October 20, 2026PHP maintainers gave advance notice of two critical upcoming vulnerabilities
October 21, 2026PHP issued fixed releases for supported PHP 8.2–8.5 branches
October 21, 2026Cloudflare reported early attack activity, while watchTowr said it was observing attempts to exploit the newly disclosed flaws

Cloudflare deployed web application firewall rules for known PHP2Shell methods before the public release and reported early attacks. The rules can add friction but do not replace upgrading: the attack techniques depend on low-level PHP behavior and can vary across environments. The reporting does not establish a confirmed successful compromise from these flaws as of October 21. WatchTowr said it was observing exploitation attempts, while adding that it had not seen a successful one at that point.

Mitigations change the failure mode, not the requirement to patch

CVE-2026-109618 has a temporary configuration measure that will look backwards to many administrators: set memory_limit=-1 administratively and ensure an application, directory, or pool setting cannot restore a finite per-request PHP memory limit. That removes the predictable limit used in the demonstrated exploit. It does not remove all allocation-failure paths, which is why the project explicitly says it is incomplete.

The change shifts the availability boundary. The advisory suggests a container or cgroup memory limit as an alternative boundary, but warns that killing a cgroup or container may kill the master process and every worker unless workers are isolated into separate groups. It specifically says not to use RLIMIT_AS or RLIMIT_DATA: forcing mmap() to fail can trigger the same vulnerable longjmp() path.

Teams that cannot patch immediately should keep post_max_size conservative, independently enforce decoded request size at the frontend, and bound nesting, input variables, multipart parts, headers per part, and uploads. If an application does not use multipart form data, blocking multipart requests before they reach PHP reduces exposure. These controls also reduce hard-OOM and denial-of-service risk after patching, but they do not replace the fixed runtime.

CVE-2026-109619 has no universal configuration workaround because any reachable application, extension, or server path might publish stale request-owned state or consume it. On PHP 8.5, disabling fatal_error_backtraces and restarting every worker removes the producer used in the confirmed fatal-backtrace RCE case. Disabling session.upload_progress.enabled and restarting workers blocks the demonstrated session lifecycle path. Both measures leave other state families and extension behavior in play.

Changing error_reporting, hiding errors with @, disabling display_errors, or disabling log_errors does not prevent the stale-state vulnerability. The unsafe global state can be accessed before PHP decides whether to emit a visible or recorded diagnostic. Likewise, placing old directives in php.ini is not identical to allowing per-request overrides. The advisory identifies .htaccess and Apache per-directory PHP configuration as early consumers for mod_php. For FPM, the concern is a frontend passing PHP_VALUE or PHP_ADMIN_VALUE parameters that generate a diagnostic before request initialization.

If performance is not the priority during containment, the project says pm.max_requests=1 can limit how many requests a worker executes. It reduces risk rather than repairing the issue: the issue can still occur within the conditions needed for a producer and consumer sequence, and the full state-reset patch is the only reliable answer.

Inventory is the hard part

This is the same operational problem identified in October’s Patch Tuesday inventory work: the patch may exist, but the organization first has to know where the component lives and whether the installed environment can accept the fix. PHP makes that task harder because it may sit below a CMS, hosting control panel, appliance, third-party service, or a vendor-maintained package rather than a team’s own repository.

The public exposure figures are not directly interchangeable. One report puts PHP’s role at 75% to 80% of websites and cites VirusTotal estimates of more than 5.1 million PHP hosts online, roughly 3.8 million with at least one port open. Another relayed Wiz’s estimate that roughly 70% of the internet could be affected, while noting that figure could not be independently verified. Those are different population claims, not a measure of confirmed vulnerable deployments.

Organizations should begin with internet-facing PHP, then trace backward through reverse proxies, FPM pools, Apache modules, managed hosting, web-admin interfaces, and products that embed PHP. They should identify the runtime branch and SAPI. That distinction determines which documented attack behavior is confirmed, but it should not determine whether a vulnerable supported package is patched.

The UK National Cyber Security Centre, European incident responders, and other national agencies have advised organizations that cannot remediate promptly to consider taking affected systems offline. Some public sites in Finland, the Netherlands, France, the United Kingdom, and elsewhere became unavailable around the disclosure. Not every outage was confirmed as PHP-related, but the precaution is rational when the alternative is leaving an unauthenticated server-side code-execution path exposed during an active scanning window.

After updating, teams should not treat a package version check as the end of the incident. The advisories recommend reviewing web-server, PHP, proxy, and service logs for fatal errors, parse errors, uncaught errors, timeouts, deprecations, warnings before target scripts run, and cleanup-time diagnostics. Historical logs may not contain the evidence: relevant severities may have been excluded, the failure may have occurred before PHP recorded it, and an audit only covers routes and application states actually exercised.

What the reporting shows

Across the four accounts, the core facts are consistent: these are critical unauthenticated RCE flaws, fixes arrived on October 21, and early malicious activity was already being observed. The accounts differ on details that matter for response. Broad reports frame PHP2Shell as an internet-wide threat; the technical advisories describe specific OOM, shutdown, stale-state, and request-lifecycle paths that behave differently under mod_php and FPM.

The immediate priority is to enumerate every web-serving PHP runtime and establish its branch, patch level, SAPI, worker model, and configuration source. A WAF can cover known requests. A disabled upload-progress feature can break one chain. A lower request limit can constrain another. None answers whether an unpatched PHP runtime is hidden under a service the organization forgot was using it.

Risk is highest where that answer is unclear: legacy PHP, externally reachable hosting stacks, per-request configuration overrides, applications with attacker-reachable fatal paths, and infrastructure whose owner cannot quickly restart workers after changing controls.

Frequently asked questions

Which PHP versions fix PHP2Shell?+

The fixed releases are PHP 8.5.12, 8.4.27, 8.3.36, and 8.2.35. PHP 8.1 and older are no longer ordinarily supported upstream; organizations need an upgrade, vendor fix, or applicable source backport.

Does PHP-FPM avoid the PHP2Shell flaws?+

No. The documented exploit conditions differ from Apache mod_php, but CVE-2026-109619 session-lifecycle RCE was validated with FPM. FPM deployments still need the fixed release.

Can a web application firewall fully block PHP2Shell?+

No. Cloudflare deployed rules for known methods, but the PHP project says updating is the only complete mitigation. Configuration and WAF controls reduce exposure to particular paths.

What should administrators do if they cannot patch PHP immediately?+

Consider taking exposed systems offline. The PHP advisories describe temporary controls including administrative settings, multipart request limits, disabling session upload progress, and worker restarts, but none fully replaces patching.

Sergey Kuznetsov

Editor-in-Chief

Sergey Kuznetsov is Head of Product at iXBT.com, one of the largest Russian-language technology media outlets, and the founder of itzine.ru. He has spent over a decade building and running tech newsrooms. At for(geeks) he sets editorial standards and reviews what ships.

/ Keep reading