PHP2Shell: Two Critical PHP Vulnerabilities, and How to Reduce the Risk Until You Patch

CVE-2026-109618 and CVE-2026-109619 – what they mean, who is affected, what to do right now, and what a WAF can do in the meantime

Vulnerabilities: CVE-2026-109618, CVE-2026-109619 ("PHP2Shell")

Severity: CVSS 9.2 – critical, both of them

Type: unauthenticated remote code execution (RCE) in the PHP engine

Fix: 21 October 2026 – PHP 8.5.12, 8.4.27, 8.3.36, 8.2.35

Affected: every PHP installation that serves web requests – regardless of the web server

On 20 October the details leaked. On 21 October PHP released an emergency fix. By the time the update appeared, exploitation attempts had already been seen. At moments like this there's no time for long deliberation – but there's no point in panicking either.

Since 2005 I've been running IT infrastructure for healthcare providers in Hungary, where a WAF has always stood in front of every internet-facing system. Over the past two days many people have asked me what this flaw means in practice and what needs to be done. On this page I summarise the facts and the actions. What it means exactly for a WordPress site, a web shop or an API running in Kubernetes, I've written up in a separate risk handbook.

The Two Flaws – in Plain Language

Both flaws are in the PHP engine itself, not in a plugin or framework. So it doesn't matter whether WordPress, Laravel, Magento or a custom application runs on it, and it doesn't matter whether Apache, Nginx or IIS sits in front.

CVE-2026-109618 – when memory runs out

If PHP runs out of memory while processing a request, it exits halfway through, while the request data is only partly set up. The cleanup code then trusts this half-built data – and that leads to code execution. It can be triggered with specially crafted multipart requests.

CVE-2026-109619 – the "stuck" pointer

PHP keeps a global pointer to a memory area that belongs to a specific request. If that pointer isn't reset, the next request handled by the same worker uses memory that has already been freed – which also leads to code execution. Long-lived workers, such as PHP-FPM, make this especially convenient for an attacker.

What does "unauthenticated remote code execution" mean? It means the attacker doesn't need to log in or know a password, and the user doesn't need to click anything. A well-crafted HTTP request is enough for the attacker to run code with the web server's permissions – and through that, reach everything the website itself can reach, including the database.

Which Server Setups Are Affected?

Web server / PHP modeCVE-2026-109618CVE-2026-109619Notes
Apache + mod_phpAffectedAffectedHighest risk: can trigger before any application code runs
Apache + PHP-FPM (proxy_fcgi)AffectedAffectedLong-lived FPM workers suit 109619
Nginx + PHP-FPMAffectedAffectedSame as above
IIS + FastCGI (php-cgi.exe)AffectedAffectedphp-cgi is explicitly in scope; workers are reused for many requests (instanceMaxRequests); the pre-application path is confirmed only for mod_php
LiteSpeed (lsphp)AffectedAffectedNamed in the advisory
FrankenPHPAffectedAffectedNamed in the advisory
PHP CLI (cron jobs, scripts)Not exposedNot exposedDoesn't serve web requests

An often-forgotten case: many Windows/IIS servers host several sites, and one of them has a PHP FastCGI handler installed. In that case the server is affected even if your own site doesn't use PHP. Always check at server level, not just at site level.

Which Versions Are Affected, and Where Is the Fix?

PHP branchVulnerableFixed inStatus
8.5< 8.5.128.5.12Official release
8.4< 8.4.278.4.27Official release
8.3< 8.3.368.3.36Official release
8.2< 8.2.358.2.35Official release
8.1 / 8.0 / 7.4AllNo official releaseSource backports only, or a distro / LTS vendor package
7.3 and older (from 5.4)AllNo fixTreat as vulnerable – upgrade
After updating, every PHP worker has to be restarted, otherwise the old code keeps running in memory: systemctl restart php-fpm for PHP-FPM, restart Apache for mod_php, and recycle the application pool or run iisreset on IIS. For containers, the image has to be rebuilt and redeployed – running pods stay vulnerable on the old image.

"So Why Don't We Just Patch Everywhere Right Away?"

That's what one of my colleagues asked, and it's a fair question. We have to update; there's no debate about that. But in production – especially in healthcare, finance, or wherever a dozen applications run on one server – a PHP update doesn't work like "it's out today, it's live tomorrow".

  • Compatibility and dependencies: plugins, the framework and the custom code all have to work with the new patch version.
  • Change management: approval, a maintenance window, communication to those affected.
  • Rollback plan: if something doesn't work, you need to know exactly how you'll roll back, and how long it takes.
  • Old branches: for PHP 8.1 or older there's no simple patch – that needs a version upgrade, which is already a project.

Something has to protect the system in the time until the update. That's why the WAF, the firewall and segmentation exist. It isn't an excuse for delay – it's part of responsible operations.

How long an organisation can afford to carry the risk, and who decides on a shutdown, isn't determined by the vulnerability but by the BCDR. I've written about that, and about the three options I give in these situations, on a separate page.

Mitigation Step by Step

1. Inventory – where does PHP run?

Every server and container running PHP has to be mapped: shared IIS hosts, old "forgotten" systems, test environments that are accidentally exposed to the internet. You can't update what you don't know about.

2. Update and restart the workers

PHP 8.5.12 / 8.4.27 / 8.3.36 / 8.2.35 – tested, then restart every worker or redeploy the containers. Start with the most critical systems: where there's personal data, payments or health data.

3. Harden the PHP configuration

; Disable the upload-progress feature (CVE-2026-109619 path)
session.upload_progress.enabled = 0

; Low POST size – matched to what the application really needs
post_max_size = 10M

; PHP 8.5 only
fatal_error_backtraces = 0

4. Temporarily strict WAF rules

Since these are memory-corruption bugs, there's no single clean attack pattern to block. The WAF rules narrow the attack paths:

  • block multipart/form-data on every endpoint that doesn't legitimately accept file uploads;
  • limit the request body size, the number of POST fields and files, and parameter nesting depth;
  • block the PHP session upload-progress field – one known attack path;
  • reject malformed multipart requests.

You'll find the concrete ModSecurity and IIS rules, collected from my own knowledge base, on the page about WAFs. Test them in detection mode first.

5. Hunt for signs of compromise

  • new, unknown admin accounts;
  • unknown PHP files (web shells) in the web directory;
  • modified payment (checkout) scripts;
  • unusual outbound traffic or large database exports.

If you find any sign of these: incident response, and if personal data is involved, personal data breach handling under the GDPR.

The PHP developers are clear: there is no complete mitigation for this flaw, and updating is the only safe fix. WAF rules and php.ini settings buy time – they don't replace the fix.

What I've Seen Over the Past Two Days

We tested it in several places: where the WAF I operate runs with the recommended settings, the vulnerability could not be exploited. We keep fine-tuning the rules, because every application behaves differently.

This flaw isn't the first and won't be the last. Just as with OpenSSL, similar ones will keep coming for PHP too. A well-built environment – firewall, WAF, segmentation, regular penetration testing – doesn't make updating unnecessary, but it gives you the time to do it properly, tested.

The point in one sentence: the webmaster always has to update the PHP engine – and until then, the WAF protects what the update hasn't yet been able to.

Related Pages

This page reflects publicly available information as of 23 October 2026, and I'll update it as new details emerge.