Try For Free

X
PHP2Shell: Finding and Patching CVE-2026-109618 and CVE-2026-109619 on Every Server You Own

PHP2Shell: Finding and Patching CVE-2026-109618 and CVE-2026-109619 on Every Server You Own

Linux Patching Patch Management

On October 20, 2026, the details of two unpatched remote code execution flaws in PHP leaked a day before their coordinated disclosure. By the time the PHP team shipped fixed releases on October 21, attackers were already probing servers. The pair has been named PHP2Shell, and it is the kind of vulnerability that turns patch management from a monthly routine into a same-day scramble.

This article covers what the flaws are, why they are harder to close than a normal PHP update, and how to run the response as a controlled patch cycle instead of a hunt across spreadsheets.

What PHP2Shell is

CVE-2026-109618 and CVE-2026-109619 are two bugs in PHP core, each rated 9.2 on CVSS v4.0 by the PHP security team. Both sit in the way PHP handles request state around the session upload-progress feature. One is triggered when PHP runs out of memory while setting up a request and later treats the half-initialised data as valid. The other is a use-after-free: request state survives after its memory is released, and a later request handled by the same worker can reach it.

The result is the same in both cases. An unauthenticated attacker sends a crafted HTTP request and runs code as the PHP worker. No login, no plugin, no application bug required.

Affected versions are PHP 5.4.0 through 8.5.11, which in practice means every PHP server deployed in the last fourteen years. Fixed releases are PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35.

Why this one is different

  • The leak came first. Most critical PHP fixes arrive with a patch and a quiet week before exploits appear. Here the exploit details were public before any fix existed, a working proof of concept followed within hours, and Cloudflare logged the first attacks at 07:43 UTC on October 21, before many teams had read the advisory.
  • PHP is everywhere, including where you forgot. Shodan counts about 1.9 million internet-facing hosts that advertise PHP, and that is the visible minority. Inside an enterprise, PHP runs the wiki, the monitoring dashboard, the ticketing portal from 2017, the vendor appliance’s admin page and the internal app nobody owns.
  • Nearly half of exposed hosts can never get the upstream fix. Of those 1.9 million, about 884,000 run PHP 8.1 or older. Those branches are end of life and will not receive a release from php.net. Their only route is a backported package from the operating system vendor, or an upgrade.
  • The workaround is partial. Turning off the upload-progress feature (session.upload_progress.enabled = Off) closes one of the two paths. The PHP team’s position is that patching is the only real mitigation.

The patching problem underneath

Knowing the fix exists is the easy part. Four things slow teams down on a day like this.

  1. Nobody has the list. Which servers run PHP, at what version, from which source? The answer is spread across package managers, a CMDB that is six months stale and a few people’s memory.
  2. The version number is the wrong thing to chase. On RHEL, Rocky Linux, AlmaLinux, Ubuntu, Debian and SUSE, the fix arrives as a vendor advisory that backports the patch into the distribution’s own PHP version. A RHEL 8 server on PHP 8.0 can be fully fixed while still reporting 8.0. Teams that compare version strings to php.net will either patch twice or declare servers vulnerable that are not.
  3. Isolated servers are last and most exposed. Air-gapped and restricted-egress estates cannot pull the new packages. They are also where the oldest PHP tends to live.
  4. A PHP update is not done until the worker restarts. Updating the package without restarting php-fpm, Apache or nginx leaves the old code running in memory. Scanners will report the server fixed while it is not.

A five-step response

  1. Inventory. Build the list of every server with a PHP runtime: php, php-fpm, php-cli and the module packages, plus PHP bundled inside applications. Include the Windows servers running PHP under IIS.
  2. Map the CVE to the fix each server can take. For each operating system, identify the advisory that carries the backport and which servers it applies to. Note the servers whose distribution has not yet published a package.
  3. Mitigate where you cannot patch yet. Apply the upload-progress setting, put the web application firewall rule in front, and watch for POST requests carrying the upload-progress field and for 5xx responses from PHP workers, which are a crash signal from a failed attempt.
  4. Patch as an emergency cycle. Stage the packages in advance, run the update in parallel across groups, restart the PHP worker and web server as part of the job, retry failures automatically and roll back any server where the application breaks.
  5. Verify and report. Confirm the running version on each server, not the installed package, and produce the list that security and audit will ask for: in scope, fixed, pending, with timestamps.

How JetPatch runs those five steps

JetPatch is built for exactly this shape of problem: a vendor-released fix that has to reach every server in a mixed estate, quickly, with proof.

  • Inventory in minutes, not days. The package inventory shows every Linux server with PHP packages and their versions. Software Discovery finds PHP installed outside the package manager and on Windows servers, so the list is complete rather than the list of what the package manager knows.
  • Advisory-level patching with CVE correlation. JetPatch tracks the vendor advisories (RHSA, RHBA, USN and their equivalents) and maps CVE-2026-109618 and CVE-2026-109619 to the package each server needs. The view is “fixed by this advisory, available for these servers, not yet published for those”, which is the question the incident call is asking.
  • Emergency remediation plans. A plan scoped to the affected servers, with pre-download so the window is spent installing rather than fetching, parallel execution by group, pre and post scripts that restart php-fpm and the web server, automatic retries and rollback. Endpoint Readiness checks run first, so servers with a pending reboot, a full disk or a stuck update service are fixed before the run instead of failing during it.
  • Predictive Patching. Simulates the cycle against the real servers first, so the team knows which hosts will take longest and which will fail, and can order the run accordingly.
  • Air-gapped and restricted networks. Only the JetPatch Manager reaches the vendor repositories. Isolated servers patch from the local repository with no outbound connection, on the same plan and the same report as everything else.
  • Windows alongside Linux. PHP under IIS is a custom package rather than an OS update. JetPatch’s Software Distribution pushes it to the right servers with the same scheduling, retries and reporting.
  • Evidence. The compliance report lists every in-scope server with its before and after state and the time it changed. That report is what closes the ticket with the CISO.

What JetPatch does not do

JetPatch does not patch faster than the operating system vendor publishes the backport. For a day or two after a leak like this, some distributions will have no package, and the value during that window is the inventory, the mitigation and the staging, so the patch runs the hour it lands. PHP compiled from source, or shipped inside a vendor appliance, is not a package the OS tracks; JetPatch can distribute a replacement build, but someone has to produce it. And PHP on a hosted platform is the host’s responsibility, not yours.

The lesson that outlasts PHP2Shell

Every few years a flaw lands in something that runs everywhere: OpenSSL, Log4j, now PHP. The teams that close it in a day are not the ones with the fastest hands. They are the ones who already know what runs where, patch by advisory rather than by version string, and can run an unscheduled cycle without a bridge call to coordinate it. That capability is built in calm months, and it is the real reason to treat patch management as infrastructure rather than a task.

Frequently asked questions

Which PHP versions are affected by PHP2Shell?

PHP 5.4.0 through 8.5.11. Fixed releases are 8.5.12, 8.4.27, 8.3.36 and 8.2.35. Versions 8.1 and older are end of life and will not get an upstream release, so they depend on operating system vendor backports or an upgrade.

Is disabling session.upload_progress enough?

No. It closes one of the two attack paths and is worth applying on servers you cannot patch immediately, but the PHP security team’s position is that updating PHP is the only complete fix.

My RHEL server still reports PHP 8.0 after patching. Is it vulnerable?

Not if the vendor advisory that backports the fix is installed and the PHP worker has been restarted. Red Hat and other distributions patch within the existing version number. Check the advisory and the running process, not the version string.

How do I know the fix is actually running?

Confirm that php-fpm, Apache or nginx restarted after the package update. A server with the new package installed and the old worker still in memory is still exploitable.

How does JetPatch help with PHP2Shell on air-gapped servers?

The JetPatch Manager fetches the vendor packages on your schedule and serves them from a local repository. Isolated servers patch from that repository with no outbound connection, and appear in the same inventory and compliance report as connected servers.

Adil Basha
schedule demoORlearn more
Start Patching the Right Way
Free Trial
✖