11 min read

PHP2Shell is exploited in the wild: patch PHP and restart its workers

Unauthenticated requests can execute code through these PHP engine flaws, and Amazon saw attempts days before disclosure. Updating WordPress or Laravel alone cannot fix them.
PHP2Shell patch guide showing fixed upstream versions 8.2.35, 8.3.36, 8.4.27 and 8.5.12, with patch, restart and verify steps.

On 21 October 2026, PHP released fixes for two critical vulnerabilities, CVE-2026-109618 and CVE-2026-109619, collectively called PHP2Shell. An unauthenticated attacker can exploit affected request-handling paths to execute code with the PHP web worker's privileges. The PHP project puts all installations serving web requests in scope, including PHP-FPM, Apache mod_php, php-cgi, FrankenPHP and LiteSpeed. PHP security advisory

Amazon reports that PHP2Shell is being broadly exploited in the wild. It recommends responding to critical internet-facing vulnerabilities within hours, rather than relying on seven- or 30-day patch schedules. Install a fixed PHP runtime and replace the processes running the vulnerable code. Amazon's exploitation report

Updating WordPress, Laravel, a plugin or an application dependency alone will not apply the interpreter fix. Automattic's runtime guidance

The fixed upstream releases are:

Your PHP branch First fixed upstream release
8.2 8.2.35
8.3 8.3.36
8.4 8.4.27
8.5 8.5.12

Linux distributions can backport the fixes into packages with older-looking version numbers. Use the upstream table for upstream builds, and your vendor's complete package version for vendor builds. The guidance and linked response pages were checked on 22 October 2026.

Patch the PHP package or image, restart serving and background workers, then verify the runtime through each application's web path.

In this guide:

What the two bugs do

PHP creates internal state for each web request, uses it while executing the application, then cleans it up. Both vulnerabilities involve failures around that lifecycle, but the unsafe memory access happens at different points.

CVE-2026-109618 involves an interrupted allocation. PHP can run out of memory while some request data is only partly initialized. Its out-of-memory handling jumps out of the current operation, leaving invalid state that cleanup later treats as valid. An attacker who controls the relevant request data and memory layout can turn that corruption into code execution. The advisory describes several ways multipart parsing can exhaust memory, including internal allocations much larger than the incoming data. OOM corruption advisory

CVE-2026-109619 involves state surviving its request. A worker can retain references to memory that belonged to a completed request and has since been freed. A subsequent request handled by that worker can use the stale reference before normal initialization resets it. The demonstrated attack requires both an operation that leaves the stale state and a later operation that consumes it. Fatal errors, session handling and some early configuration diagnostics can participate in these paths. Stale-state advisory

The upstream patches change these engine behaviors. The OOM fix replaces the unsafe bailout with controlled handling at a safe execution point, with a separate hard-stop threshold. The state-lifecycle fix addresses retained references. Ordinary application-level input validation cannot substitute for these changes.

Why the release became an emergency

In 2024, a PHP core developer contracted by the PHP Foundation found signs of the OOM problem while addressing audit findings. No concrete path to remote code execution was established; compatibility, performance and extension tradeoffs stalled fixes. On 11 August 2026, Calif and OpenAI independently reported the root cause, and fixing it became the team's top priority. The Foundation acknowledges failures in its decision process and resourcing.

On 20 October, leaked identifiers and incorrect release information prompted PHP to advance its scheduled 22 October, 14:00 UTC release to 21 October, 14:00 UTC. Both flaws carry CVSS v4.0 scores of 9.2, rather than the leaked 10.0. PHP's severity announcement

The Foundation says Calif accidentally published a proof-of-concept (PoC) video around 20:00 UTC on 20 October, then deleted it. It also says Chainguard published fixed images at 07:41 UTC on 21 October, more than six hours before coordinated disclosure, letting attackers study the fix in binary form while other users waited for packages. Foundation's discovery and release account

Chainguard CEO Dan Lorenc, posting on HN as dlor, said he chose to release early because exploits were already in the wild. Amazon observed PoCs around 02:00 UTC on 21 October, further attempts before disclosure, and new PoCs used against its sensors within hours after the patch. Amazon's timeline

The gap between published source and deployable packages appeared in community reports. An HN commenter reported Docker images still unavailable after disclosure, while a Reddit discussion questioned whether new image tags had usable manifests. Those were reports from the release window. For an update now, inspect the artifact and package your deployment actually uses.

Which deployments are affected

The PHP advisory's broad scope is important, but the exploit paths differ by server interface. PHP calls this interface the SAPI, or Server Application Programming Interface.

Deployment What the technical reports establish
Apache with mod_php The OOM attack was demonstrated with default input and memory limits, before application code starts. The stale-state advisory also documents confirmed code execution.
PHP-FPM Failed request startup causes the child to exit, blocking the early mod_php OOM path. The Foundation reports confirmed OOM RCE during application execution. The stale-state advisory separately confirms session-lifecycle RCE.
FrankenPHP Included in PHP's affected scope. The OOM advisory says it calls request shutdown unconditionally, like mod_php, making application-independent attacks likely.
LiteSpeed/LSAPI Included in PHP's affected scope. The OOM advisory says LSAPI behaves like FPM, with application-specific exploits likely but unvalidated.
php-cgi and other PHP web deployments Included in the project's update advice. Determine the installed runtime and follow the relevant vendor guidance.

The sources differ on OOM demonstration status. The OOM advisory says no complete FPM exploit was demonstrated for that SAPI; the Foundation explicitly reports confirmed application-stage FPM RCE. The separate stale-state advisory also confirms FPM exploitation. None of these sources excludes FPM from patching.

Red Hat rates CVE-2026-109618 Important, with CVSS v3.1 8.1, reflecting RHEL's default FPM deployment and harder application-dependent exploitation. PHP's Critical, CVSS v4.0 9.2 rating uses a different scoring system and scope. Use the Red Hat CVE entry for the status of your Red Hat product.

Wiz reports that every PHP version released in the last decade, back to PHP 5.4, is affected by at least one of these issues. The exact behavior depends on the version and configuration. Avoid treating the two CVEs as an identical exploit against every historical PHP build. Researcher's scope assessment

If you are testing PHP 8.6 prereleases, 8.6.0 RC4 includes the fixes. Earlier builds need updating. Its versioned release notes record both CVEs. This release candidate is for testing; production applications on PHP 8.2–8.5 should use their fixed stable branch.

Find the PHP runtime your application uses

Start with the site configuration and deployment inventory. Identify the PHP branch assigned to each virtual host or FPM pool, the package repository or image that supplies it, and the service that starts it. Include administrative tools, staging sites and vendor applications that expose PHP endpoints.

Inventory itself was a problem in the r/sysadmin discussion: an administrator described missing bundled PHP executables when searching only common locations. Your main web application's package list may cover only part of the estate.

On a host, these commands inspect the selected command-line interpreter:

php -v
php --ini

PHP documents -v as a version/SAPI check and --ini as a configuration-file listing. The commands describe the CLI binary you invoked. A site's FPM pool may use another installed branch or configuration. PHP CLI options

For the actual serving path, use existing authenticated diagnostics or a temporary access-restricted route that reports only what you need:

<?php
echo phpversion(), " ", php_sapi_name(), "\n";

phpversion() identifies that process's runtime, and php_sapi_name() identifies its interface. Check every separately deployed replica or runtime pool. Remove temporary diagnostics afterward. A public phpinfo() page exposes much more, including configuration, paths and environment information. PHP information disclosure details

Apply the fix to hosts, containers and managed services

Distribution packages and upstream builds

For an upstream build, move to the fixed patch release in your supported branch. For a distribution package, compare the full package version with the security notice for that distribution and release.

For example, Ubuntu's security notice lists:

Distribution Fixed distribution package
Ubuntu 24.04 LTS, PHP 8.3 8.3.6-0ubuntu0.24.04.13
Ubuntu 22.04 LTS, PHP 8.1 8.1.2-1ubuntu2.28

Those packages contain the fixes even though their base numbers differ from the upstream table. Ubuntu USN-8948-1

Red Hat also explains that it backports security changes instead of always replacing packages with a new upstream release. A scanner that checks only the base PHP version can therefore flag a fixed vendor package. Check the product's CVE entry and security errata, including the package release suffix. Red Hat's backporting policy

On Ubuntu, list installed interpreter packages with the security team's check command:

apt list '?installed ?name(^php[0-9.]+$)'

Ubuntu's fixes for 20.04 LTS and older require Ubuntu Pro ESM. Where unattended-upgrades covers the affected Ubuntu packages, Ubuntu says it installs available security fixes within 24 hours; affected applications still need restarting or the host rebooting. Check the installed package and process state instead of assuming automatic updates completed the response. Ubuntu's package and restart guidance

On Ubuntu using its distribution repositories, the security team's general update instructions are:

sudo apt update
sudo apt upgrade

Review the transaction through your normal deployment process. Then restart the processes loading PHP. Ubuntu specifically calls out restarting Apache for mod_php, or rebooting to replace processes using updated components. For FPM, restart the relevant PHP-FPM service and confirm that every affected pool has new workers.

For a systemd host whose PHP 8.3 service is named php8.3-fpm, for example:

sudo systemctl restart php8.3-fpm
php-fpm8.3 -v

Adapt the service and binary names to your installation. The second command checks a new FPM binary invocation, as in Forge's verification example; it cannot prove that an existing daemon or worker was replaced. Confirm the restart completed, check worker replacement, and request the restricted web diagnostic through each affected pool or replica.

Third-party PHP repositories have their own package builds. Before assuming the update succeeded, inspect the package candidate, for example apt-cache policy php8.3-fpm on a host using that package name, and compare it with the repository's advisory.

For RHEL, AlmaLinux or Rocky Linux systems using Remi, PHP's 21 October advisory warned that updates would not be available that day and urged an alternative. That warning is no longer a reliable availability check: on 22 October, Remi's Enterprise Linux 8 x86_64 listings include fixed PHP-FPM 8.3.36 and 8.4.27 packages. Verify your own branch, operating-system release, architecture and enabled repository or mirror before upgrading. These two listings do not establish availability for every Remi stream.

Docker and custom application images

Updating PHP on the host leaves the PHP interpreter inside an existing container unchanged. First select an image containing the fixed runtime. If your deployment pins an old tag or digest, change that reference.

For a Compose service named php that uses a published image, a deployment sequence is:

docker compose pull php
docker compose up -d --no-deps --force-recreate php
docker compose exec php php -v

Replace php with your service name. pull downloads an image without starting it; up recreates the service. Plan for the service interruption or use your platform's rolling replacement process.

If you build your own image, update the Dockerfile's base reference and rebuild with docker compose build --pull php before recreating the service. Docker's --pull option attempts to fetch a newer base image; it cannot turn a pinned vulnerable digest into a patched one.

The final command runs a new CLI process in the running service container. Also check the web-runtime diagnostics and replacement of the serving processes described above. Carry the fixed image reference into CI and deployment configuration so the next release retains it.

Managed hosting and server-management tools

Ask the provider for the patch status of the specific product and runtime your site uses. Distinguish a fully managed application platform from a tool that manages servers you remain responsible for updating.

For example, Laravel Forge says its automatic security updates do not patch PHP. It uses Ondřej Surý's packages, including an ondrej/php PPA mirror on Ubuntu 22.04 and 24.04. Forge provides dashboard and SSH update paths and instructs operators to update every installed PHP branch. Its guide also calls out long-running CLI processes, including queue workers, Horizon, Octane and Reverb, which keep using their old interpreter until restarted. Forge's PHP security guide

Automattic, by contrast, says sites on WordPress.com, WordPress VIP, WP Cloud, Pressable and Tumblr are protected. That statement covers those named hosted services. Self-hosted WordPress owners still need their own runtime or hosting-provider update. Automattic's platform statement

PHP 8.1 and older

Normal upstream security releases have ended for these branches. Some vendors supply backports, including Ubuntu's documented fixes for older supported distribution packages. PHP also published minimal source backports for 7.4, 8.0 and 8.1 for people maintaining their own builds. Confirm what your vendor or build contains against the PHP release advisory.

Without a supported vendor package, move to a maintained, fixed runtime or restrict access while arranging that migration. Separate the emergency patch from the longer upgrade plan. PHP 8.2 itself reaches the end of upstream security support on 31 December 2026. PHP support calendar

Temporary controls while you arrange the update

Both technical advisories say a patched runtime is the only complete resolution. Configuration changes reduce particular paths. If you cannot establish a patched runtime, restricting access before requests reach PHP is the most conservative interim deployment choice.

For the OOM vulnerability, PHP's release guidance gives these interim settings:

  • Enforce memory_limit=-1 with an administrative setting such as php_admin_value in FPM pool or Apache configuration. Confirm no pool, directory or application restores a finite limit.
  • Set post_max_size=8M for applications without file uploads, or 32M where uploads are necessary. Keep upload_max_filesize below post_max_size.
  • Enforce decoded body-size limits at the web server or proxy, including requests without a usable Content-Length. Bound input variables, multipart parts, per-part headers and nesting too.

Removing PHP's limit eliminates a predictable OOM trigger, but underlying allocations can still fail. Use a container or cgroup memory limit as an availability boundary, preferably isolating each worker so an OOM kill does not take down the master and all workers. The OOM advisory says this is not guaranteed to prevent allocation failure and is not a complete mitigation. Do not substitute RLIMIT_AS or RLIMIT_DATA, which can provoke the vulnerable allocation-failure path.

If the application does not need multipart requests, blocking them before PHP reduces relevant attack paths. Uploads and forms that depend on multipart bodies will stop working.

For the stale-state vulnerability, the official guidance includes:

  • Set session.upload_progress.enabled=0 to remove demonstrated early session paths.
  • On PHP 8.5, set fatal_error_backtraces=0 to remove the confirmed fatal-backtrace path.
  • Remove invalid or deprecated configuration that produces diagnostics before request initialization, and address attacker-reachable fatal errors.

Apply relevant settings through startup, pool or server configuration and restart workers. An application-level ini_set() or FPM .user.ini change can be too late for the early request paths. Hiding warnings with display_errors, error_reporting or @ leaves the underlying condition intact.

The stale-state advisory also mentions pm.max_requests=1 when the performance cost is acceptable. Recycling a worker after one request reduces the cross-request chain. It does not repair the separate OOM failure, so it should never become the criterion for declaring a deployment patched.

Cloudflare says its WAF protection was active from 03:02 UTC on 21 October. Free customers receive the rules automatically through its Managed Free Ruleset. Pro, Business and Enterprise customers should confirm the Cloudflare Managed Ruleset is deployed in block mode. Cloudflare still recommends updating PHP. Provider's protection and deployment instructions

Check the traffic path too. Requests reaching an exposed origin directly can bypass the proxy's filtering. Cloudflare documents restricting access to the origin. A WAF rule is an additional control while you patch and investigate.

Verify the deployment and review earlier exposure

Record the package or image reference installed, restart or replacement time, and the version reported through each application's serving path. Check ordinary application behavior afterward, including authentication, uploads and any long-running PHP services you restarted.

Then examine the period before the update. Amazon reports an exploitation attempt against its MadPot honeypots on 17 October, plus further attempts before public disclosure on 21 October. Its report says whether the pre-disclosure attempts would have succeeded against real systems remains unclear. That supports reviewing earlier exposure without assuming a particular site was compromised. Amazon's telemetry and investigation guidance

Start with preserved web, reverse-proxy, PHP and host-security logs from at least that date. Amazon recommends examining suspicious requests and unexpected process execution or file modification. A request containing PHP_SESSION_UPLOAD_PROGRESS, memory errors or HTTP 500 responses is a lead to investigate in context. Legitimate traffic and application faults can produce similar evidence.

The stale-state advisory warns that an absence of errors in logs is not proof of safety. Relevant diagnostics may have been excluded, affected routes may never have been exercised during an audit, or failure may occur before a message is written. Logging limitations

If evidence suggests code execution, isolate the affected service and preserve logs and system evidence for incident response. Assess persistence, rebuild from trusted artifacts where required, and replace credentials the compromised process could access. Installing the PHP patch closes the vulnerability; recovery also has to address any access an attacker already obtained.