Home / Insights / PHP2Shell: Why the Patch Stalls on Old PHP Code
Technical

PHP2Shell: Why the Patch Stalls on Old PHP Code

On PHP 8.2 and newer, fixing PHP2Shell is a runtime update your ICT partner can ship today. Applications on PHP 8.1 or older get no upstream fix, so the code must move first, and that job rarely has an owner.

Summarize with AI Prompt copied. Paste it into the chat

On 21 October 2026 the PHP project shipped fixes for two critical flaws in PHP itself, CVE-2026-109618 and CVE-2026-109619, now known together as PHP2Shell. An unauthenticated request can run code on the web server or read worker memory that holds passwords, tokens and API keys. Details leaked a day early, and Amazon's honeypots logged an exploitation attempt on 17 October, four days before the patch existed.

This post is for the person who has to answer for it inside a Dutch or Flemish organisation of 250 to 5,000 people: the IT manager, informatiemanager or security officer. Crux Digits does not host, patch or run servers; your ICT partner or internal IT team does that. What we add is the part of PHP2Shell that a patch cannot reach: applications whose code is too old to run on a PHP version that still gets fixes.

What PHP2Shell is

Both flaws sit in the PHP engine, below the application, so it does not matter whether the site runs WordPress, Drupal, Magento, Laravel or something written in house. The first corrupts request data when PHP runs out of memory halfway through setting a request up; the second leaves request state behind after its memory is freed, so the next request on the same worker uses it. Both are rated 9.2 on CVSS v4.0. The PHP security release names every installation that serves web requests as at risk: PHP-FPM, Apache with mod_php, php-cgi, FrankenPHP and LiteSpeed. The risk is highest on mod_php, where PHP has a working exploit that fires before any application code runs.

The fixed releases are PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35. PHP 8.1 and older get no release. The project published minimal source backports for 7.4, 8.0 and 8.1 and says to ask your distribution or vendor, or to upgrade to a supported version. The finder, Wiz, writes that one researcher working with AI models found and weaponised the bugs in about a week. That is their account, but it fits the direction of travel: flaws in old, widely deployed code are getting faster to find, for attackers as well as for defenders.

"Patch PHP" is three jobs with three owners

The advisories all end with the same instruction: update. Inside an estate of a few hundred applications, that instruction splits into three jobs that belong to three different parties, and only the first is quick.

The first job is the runtime on PHP 8.2 or newer that your ICT partner or cloud platform runs. That is a package update, and then a step that is easy to forget: NCSC-NL points out that workers which were already running keep executing the vulnerable code until they are restarted. Containers are the same story one layer up. Google's guidance is blunt that self-built images are the customer's responsibility: they have to be rebuilt on a patched base image and redeployed, not just scanned.

The second job is PHP that arrived inside something you bought: an appliance, a hosting control panel such as cPanel or Plesk, a Windows product that ships its own php-cgi.exe. Huntress lists exactly these as the installs people miss. Here the vendor patches and you track the vendor. NCSC-NL keeps an inventory of software products with a PHP dependency in the same repository, and it is worth checking your contract list against it this week.

The third job is your own PHP applications on 8.1 or older: the supplier portal built in 2017, the intranet module nobody has touched since the developer left, the Laravel or Symfony application pinned to PHP 7.4 because the framework version it uses never supported PHP 8. No upstream fix exists for these. Your ICT partner cannot simply upgrade the runtime, because the application stops working on PHP 8.2, and they do not own or change your code. This is where PHP2Shell turns from a patch into a project, and where it usually sits without an owner.

Why the version number in your inventory can mislead

Pull quote from Crux Digits: The patch is a version bump. The problem is the application nobody is allowed to bump.

Most inventories record the upstream version string, and for this advisory that string can be wrong in both directions. Distributions backport security fixes into the version they shipped, so a patched package can still report an older upstream number. Qualys says this explicitly for PHP2Shell: follow the vendor advisory, because a backported fix may keep the old version. A scanner that reads only the string will flag a patched distribution build as vulnerable and, worse, let an unpatched hand-compiled 8.3 pass if nobody checks the patch level.

Ask for four fields per PHP install instead of one: the upstream version, the package release or build source, the SAPI (FPM, mod_php, CGI, FrankenPHP or LiteSpeed), and whether it is reachable from the internet. With those four you can sort the estate into the three jobs above in an afternoon, and you can see which mod_php hosts facing the internet to treat first.

What breaks when old PHP code moves to 8.2

An upgrade from 7.4 or 8.1 is rarely a rewrite, but it is never a version bump either. PHP 8.0 removed functions that older code leans on, such as each() and create_function(), and changed how strings compare with numbers, so a comparison like 0 == "abc" now returns false where it used to return true. PHP 8.1 deprecated passing null to built-in functions that expect a string, which produces a flood of warnings in code that was written loosely. PHP 8.2 deprecated dynamic properties, which many older codebases create everywhere. On top of the language sits the framework: a framework release from before PHP 8 typically declares in its composer.json that it does not support PHP 8, so the framework has to move too, and its own breaking changes come along.

Most of this is mechanical, and good tooling exists for it. Rector applies refactoring rules per PHP version, PHPCompatibility flags code that will not run on a target version, and static analysis with PHPStan finds the type errors the new versions expose. What decides the time and the risk is whether there are tests. An application with a test suite can be upgraded step by step with each change proven; one without has to get characterisation tests first, written against its current behaviour, so that the upgrade can show it changed nothing.

A plan for this week, by owner

Today, ask your ICT partner for the four-field list above, and ask them to confirm that every worker was restarted after the update and that every container image was rebuilt. Ask each vendor on the NCSC-NL list you run for its advisory and date. These are questions, not tasks for you, and they make the first two jobs visible.

For every internet-facing install on PHP 8.1 or older, apply PHP's interim measures now: set session.upload_progress.enabled to 0 in php.ini or the FPM pool and restart every worker, keep post_max_size low, and enforce request-size limits at the web server or proxy. PHP is explicit that these measures do not make an installation safe; they buy time. Where you can, put the application behind a VPN or restrict it to known addresses until the code has moved.

Check the logs back to at least mid-October, because the first recorded attempt predates the leak. Huntress advises looking for PHP worker processes (php-fpm, httpd, apache2, php-cgi) that start shells or download tools, and for reconnaissance commands such as whoami or uname run from a web server. Wiz adds repeated HTTP 500 responses after multipart requests, memory-limit errors and unusually large PHPSESSID cookies. If you are in scope of the Cyberbeveiligingswet, a confirmed compromise may be a significant incident with an early warning due within 24 hours; our post on the supply-chain duty covers who in the chain carries that duty.

Within a month, decide for each application on PHP 8.1 or older: upgrade it, replace it, or retire it. Write the decision down with a date and an owner. An application that cannot move to a supported runtime within one sprint is a standing exposure, and the question of who holds a component's version number is the same one we raised for AI gateways two days ago.

Where Crux Digits fits

We take the third job and leave the first two where they belong. Your ICT partner keeps running the servers, applying the packages and restarting the workers. We work on the application: a code audit that shows what breaks on PHP 8.2 or 8.4, how much of it the tooling can fix, what test coverage exists and what the framework upgrade involves, followed by a fixed-scope upgrade. AI models do the bulk of the mechanical refactoring and draft the missing characterisation tests; an engineer reviews every change before it merges, and nothing ships that the tests have not proven.

What your ICT partner receives at the end is a deployable application on a supported PHP version, the test suite that proves its behaviour, and a short runbook for the next upgrade. The code stays yours. If an application turns out to cost less to replace than to upgrade, the audit says so; that is a decision for you, not a sale for us.

If you want the third job looked at, our custom software development page explains how we work with fixed steps.

Last updated: 22 October 2026.

Need custom software built?

Software built around your process and data, with AI where it changes the outcome. Something working every week, and the code is yours.

Custom software development in the Netherlands →

Frequently asked questions

Are we safe if we run PHP-FPM rather than mod_php?

No. PHP lists PHP-FPM among the affected setups. FPM's startup behaviour blocks one out-of-memory attack path, but PHP has validated remote code execution through the session lifecycle against FPM under suitable application conditions. mod_php carries the highest risk; FPM still needs the update and a restart of every worker.

Is a web application firewall enough until we can upgrade?

It is defence in depth, not a fix. Cloudflare, Fastly, Vercel and Google Cloud Armor ship rules for PHP2Shell, and Cloudflare has already seen attempts to evade its protections. PHP states that only an update is a complete solution. Use the WAF to buy time on the applications that have to move, together with PHP's interim settings and access restrictions.

Our servers run PHP 8.1 from Ubuntu or Red Hat packages. Are they patched?

Only if your distribution has published a backported fix and it is installed, and the version string will not tell you. Check the distribution's security advisory for PHP2Shell and the installed package release, then confirm the workers were restarted. The PHP project itself releases nothing for 8.1 and older, so the distribution is the only route besides upgrading.

How long does upgrading an old PHP application take?

It depends on four things you can measure before anyone quotes: the size of the codebase, the framework and how far it has to move, how much the automated tooling fixes, and whether tests exist. A code audit answers those four, so the upgrade can be scoped and fixed instead of estimated in hours. Without tests, writing characterisation tests is usually the first and largest step.
Our AI services AI consultancy AI automation AI agents AI implementation Pricing

Want any of this applied to your business?

We turn these concepts into working tools: grounded, safe and measurable. Start with a free consultation.

Book a free consultation →