PHP2Shell (CVE-2026-109618/109619): check your version, patch, mitigate

Which PHP versions fix PHP2Shell, how to check what your server really runs, the advisory’s stopgap settings, WAF limits, and CVE-2026-115560.

· Published · 9 min read · Versions: PHP 8.2, PHP 8.3, PHP 8.4, PHP 8.5

PHP2Shell is a pair of vulnerabilities in PHP itself (CVE-2026-109618 and CVE-2026-109619) that allow remote code execution without logging in, and they were exploited before the patch shipped on 21 October 2026. Is your server affected, which version do you need, and what can you do if you can't patch right away? The short answer: every web server running PHP 5.4 or later is in scope, and the only real fix is 8.5.12, 8.4.27, 8.3.36 or 8.2.35. The temporary configuration changes block only part of the attack surface.

This post pulls together PHP's advisory, the original GitHub Security Advisories, Cloudflare's and Recorded Future's analyses, and the guidance from Vietnam's Department of Cybersecurity. It covers what the bugs are, how to check the version you actually run, the mitigation settings, the limits of a WAF, the related and still unpatched CVE-2026-115560, and which logs to review. The wider picture of how AI drove up vulnerability counts is in AI and the October 2026 vulnerability storm.

PHP2Shell is a memory bug in PHP, not in your code

Updating WordPress, plugins or your framework does not fix PHP2Shell, because the bug is in the PHP runtime. According to the 21 October advisory, there are two bugs:

  • CVE-2026-109618: out-of-memory handling can interrupt PHP while internal request data is only partially initialized, and request cleanup may then treat that invalid data as valid.
  • CVE-2026-109619: request-owned internal state can survive after its memory has been freed. A later request handled by the same worker may use that stale state before it is reset.

The advisory says every PHP installation serving web requests is at risk, including PHP-FPM, Apache with mod_php, php-cgi, FrankenPHP and LiteSpeed, with the highest risk for mod_php. Cloudflare says the bugs affect all web servers running PHP 5.4 or later. Both score 9.2 under CVSS v4, but the vector in GHSA-6wmf-4rv5-p3rp rates attack complexity as high (AC:H): exploitable, but not as easy as an SQL injection.

Timeline: exploited before the patch existed

This is why "wait for the patch" was not enough. From Recorded Future, plus Cloudflare for the WAF row and php.net for 23 October:

When (UTC) What
Early Aug Ryan Austin of Calif reports a bug to PHP (per Duong Ngoc Thai)
24 Aug Wiz reports its findings to PHP
20 Oct PHP pre-announces an emergency release for 21 Oct
21 Oct, 02:29 An archive with the details is submitted to VirusTotal
21 Oct, 03:02 Cloudflare enables WAF rules for customers on every plan, including Free
21 Oct, 07:34 Patchstack gets reports of real exploitation from hosting partners
21 Oct, 13:52 PHP ships the fixes
23 Oct PHP announces CVE-2026-115560 (see below)

Recorded Future also notes that the available reporting does not establish the full extent of successful exploitation. According to Reuters, the PHP Foundation has seen no sign of attackers getting into patched systems.

Which versions are safe

Move to the fixed release of the branch you run. Branch 8.1 and older get no official release. Collected from PHP's advisory:

Branch Fixed in Notes
8.5 8.5.12 Also set fatal_error_backtraces=0 if you can't update yet
8.4 8.4.27 —
8.3 8.3.36 —
8.2 8.2.35 End of life on 31 December 2026, plan the upgrade
8.6 (testing) 8.6.0 RC4 Every 8.6.0 build before RC4 needs updating
7.4, 8.0, 8.1 No release Minimal source backports, or fixes from your distribution or an LTS vendor
7.3 and older None The advisory offers no backport for these: upgrade

A Linux distribution's PHP comes from its security repository, not the main one. On the Debian security tracker, the php8.2 package in bookworm's main repository is still 8.2.32 (vulnerable), and the fixed build is 8.2.35-1~deb12u1 in bookworm-security. If your server doesn't have the security repository enabled, apt upgrade won't bring the fix.

Check what your server actually runs

Check the PHP version your web server uses, not just the CLI. On the same machine, php on the command line and PHP-FPM can be different versions. I don't have a machine running PHP where I write, so these are the commands without output:

php -v          # CLI build
php-fpm8.2 -v   # FPM build; the binary name depends on the distribution, e.g. php-fpm, php-fpm8.3
php-fpm8.2 -i | grep -E 'session.upload_progress.enabled|memory_limit|post_max_size'

The last command shows the FPM build's php.ini values, but not overrides set in a pool file (php_admin_value, php_value), so read the pool files as well.

For containers built on the official PHP images from Docker Hub, the version is in the PHP_VERSION environment variable set in the image's Dockerfile:

docker image inspect <image> --format '{{.Config.Env}}' | tr ' ' '\n' | grep PHP_VERSION

Don't forget the places nobody remembers: staging, third-party software containers that bundle PHP, and old servers without an owner. The first step in the Department of Cybersecurity's guidance is exactly this list. If you're on shared or managed hosting, PHP is in your provider's hands: ask them whether it's patched.

Can't patch yet: the advisory's mitigation settings

PHP's advisory gives temporary settings and says plainly they are not a fix: "There are no complete mitigations, updating is the only safe choice." The advisory lists them as prose; I collected them into one php.ini block. The comments and the upload_max_filesize value are mine:

; php.ini
memory_limit = -1
post_max_size = 8M          ; 32M if the app needs file uploads
upload_max_filesize = 2M    ; any value below post_max_size
session.upload_progress.enabled = 0
fatal_error_backtraces = 0  ; PHP 8.5 only

In an FPM pool the same settings use php_admin_value or php_admin_flag (PHP-FPM configuration), which the application can't override:

php_admin_value[memory_limit] = -1
php_admin_flag[session.upload_progress.enabled] = off

What the advisory stresses:

  • Set these where they apply before request parsing: php.ini, the FPM pool, or the server configuration (for example php_admin_value). Don't rely on ini_set() or .user.ini.
  • Restart every worker after the change.
  • memory_limit = -1 targets CVE-2026-109618. The advisory warns against substituting RLIMIT_AS or RLIMIT_DATA, because those can cause the very allocation failure being exploited. The trade-off is that one request can use all available RAM, so treat it as temporary, not a setting to keep. Check that no pool, directory or application setting puts a finite limit back. A container or cgroup memory limit (memory.max) can stand in for PHP's own limit, but GHSA-w8hw-w9fx-j79w says it is not a complete mitigation either: if an underlying allocation fails, PHP can still reach the vulnerable path.
  • session.upload_progress.enabled = 0 blocks the confirmed session paths but not other variants. Turning it off also stops any upload progress bar that relies on this feature.

A WAF helps, but only under certain conditions

A WAF is an extra layer while you patch, not a replacement for the patch. Cloudflare blocked PHP2Shell from 03:02 UTC on 21 October for every customer with the WAF, including the Free plan, but states that customers who changed session.upload_progress.name from its default are not covered by the rule. Paid-plan customers should confirm their Managed Ruleset is in block mode.

The Department of Cybersecurity also recommends enabling and updating WAF rules, limiting request size and rate at the web server or proxy, and testing before rollout. One condition is often missed: if the origin server still accepts direct connections from the internet, attackers can go around the WAF. Recorded Future advises making sure origins can't be reached directly.

CVE-2026-115560: the 21 October patch is not the end

On 23 October, PHP announced another remote code execution bug that the 21 October releases don't fix, under very narrow conditions. According to PHP's informational advisory, an application must set session.serialize_handler to php_binary or php_serialize in its configuration, switch it to php at runtime with ini_set() before calling session_start(), and still have session upload progress enabled.

PHP will fix it in the next regular release and publish the full advisory then. Until that release, it suggests keeping session.upload_progress.enabled=0. If you already turned it off on 21 October for CVE-2026-109619, keep it that way until that release.

Already patched: still review logs from 20 October

Patching stops the next attack. It doesn't tell you whether someone got in earlier. Because the bugs were exploited before the fix, Recorded Future recommends reviewing logs from 20 October onward, and looking further back if you can: web server, application and endpoint telemetry. The signs listed by the Department of Cybersecurity:

  • Requests with unusually large bodies or high frequency.
  • Repeated out-of-memory errors.
  • PHP processes stopping unexpectedly.
  • Unknown files appearing on the server.

A GuidePoint expert quoted by VnExpress points out that a "clean" scan doesn't rule out a compromise. If you find signs, treat it as a real incident: isolate the machine, investigate, and rotate every credential it held (database passwords, API keys, SSH keys).

What these steps don't solve

Nothing in this post replaces moving to a supported PHP branch. The temporary settings only block known exploitation paths. A WAF blocks only the patterns it recognizes, and only for traffic that passes through it. The backports for 7.4, 8.0 and 8.1 are minimal, and the 8.2 branch reaches end of life in two months.

PHP2Shell won't be the last vulnerability either. What helps you handle the next one faster is a list of what you run, a way to update PHP that doesn't mean touching each server by hand, and logs good enough to answer "did anyone get in?"

Summary

  • PHP2Shell (CVE-2026-109618, CVE-2026-109619) is a memory bug in the PHP runtime from 5.4 onward, affecting every way of running PHP for the web. Updating plugins doesn't fix it.
  • Move to 8.5.12, 8.4.27, 8.3.36 or 8.2.35. Branch 8.1 and older get no official release. On a distribution, make sure the security repository is enabled.
  • Check the PHP-FPM or mod_php version your web server uses, not just php -v, and check containers too.
  • If you can't patch yet: apply the advisory's settings before request parsing and restart workers. A WAF is only an extra layer.
  • Keep session.upload_progress.enabled=0 until the CVE-2026-115560 fix ships, and review logs from 20 October.

If you've patched PHP2Shell across many servers and hit a snag this post doesn't cover, I'd love to compare notes. My email is on the home page.