← Back to Posts

Posts

PHP2Shell: What We Know About CVE-2026-109618 and CVE-2026-109619, and What to Do Today

PHP2Shell: What We Know About CVE-2026-109618 and CVE-2026-109619, and What to Do Today

On October 20, two critical vulnerabilities in PHP core leaked a day before their planned disclosure. They’re tracked as CVE-2026-109618 and CVE-2026-109619, and the exploit tool that leaked with them has a name built for headlines: PHP2Shell.

This one is different from the usual CMS plugin bug. The flaws sit in the interpreter, not in WordPress, Laravel, or your own code. If a server runs PHP, it’s in scope until proven otherwise.

Here’s what is confirmed, what isn’t, and what to do in the next 72 hours.

What Happened

The timeline moved fast, and most of it happened in public.

  • October 20. A post claiming two critical PHP vulnerabilities were headed for disclosure appeared and was taken down, but screenshots spread. Florian Roth posted that there was an RCE in PHP core rated CVSS 10.0, and that only PHP 8 would get patches.
  • October 20. The PHP security team published an advance notice through The PHP Foundation: two vulnerabilities, both rated CVSS v4.0 9.2, with an out-of-band security release scheduled for October 21 at 14:00 UTC, and an “earlier release if details become public or active exploit evidence.” watchTowr confirmed the bugs are real and said it had reproduced one in a lab.
  • October 20. CERT-EU issued advisory 2026-018, advising organizations to isolate internet-facing PHP applications where they can’t patch immediately. The UK’s NCSC followed with its own advisory, urging organizations to prepare to update PHP immediately and to consider taking systems offline if they can’t be fixed straight away. Cyber Security News and others picked up the PHP notice the same day.
  • October 21, before the patch. A researcher posting as J4ck3LSyN claimed to have recreated both CVEs and published a technical write-up with proof-of-concept code. Teammate Andrew Dorman described it as a joint effort with a third researcher, Archknight23, and placed the vulnerable path in PHP’s session upload progress and multipart form-data (RFC 1867) handling. Within hours, other PoC repositories started appearing on GitHub.
  • October 21, 14:00 UTC. Fixed releases are due, moved up from the original embargo date because of the leak.

The 10.0 score in early posts came from the leak. The official rating is 9.2.

What We Know, and What We Don’t

The original leak told the world that the bugs exist, how bad they are, and when the fix lands. The public write-up that followed claims to explain how they work. PHP hasn’t confirmed it. Separate the facts from the noise.

Confirmed:

  • Two vulnerabilities in PHP core, CVE-2026-109618 and CVE-2026-109619, both CVSS v4.0 9.2.
  • CERT-EU assesses them as possible remote code execution without authentication.
  • At least one independent firm (watchTowr) has reproduced one of them.
  • Fixes ship only for supported branches. PHP 8.1 reached end of life on December 31, 2025. PHP 8.0, 7.x, and 5.x are long gone. None of them will get an official patch.
  • PHP core developer Gina Peter Banyard put it bluntly: the only mitigation is patching or upgrading PHP. “I sadly know too much.” It can’t be fixed from application code.

Not confirmed:

  • The affected version range. Sansec reports that a screenshot of the PHP2Shell tool, credited to Calif.IO, claims it works against every release from PHP 5.4.0 on. Other reporting says PHP 5 onward. PHP’s advance notice didn’t say. Wait for the official advisory.
  • The fixed version numbers. Trackers expect 8.5.12, 8.4.27, 8.3.36, and 8.2.35. PHP hasn’t confirmed them as of this writing. Check php.net and the php-src GitHub security advisories before you close a ticket.
  • The root cause. The J4ck3LSyN team’s write-up describes two heap use-after-free bugs in PHP’s session upload progress handler (php_session_rfc1867_callback in ext/session/session.c), reachable during multipart parsing before any application code runs. That’s plausible, and it matches where the circulating mitigations point. It’s also disputed. Kevin Beaumont said the write-up looks LLM-generated from GitHub commits but is “roughly right on one of the issues.” Commenters on Hacker News said the PoC is incomplete, and one said it targets LiteSpeed’s SAPI rather than stock php-fpm. PHP has not confirmed the component or the attack vector.
  • In-the-wild exploitation. Patchstack says hosting partners reported multiple active exploitation incidents. Huntress and watchTowr said they hadn’t seen any as of October 20, and neither CVE was in the CISA KEV catalog at the time of writing. Those statements can all be true at once. And with a public write-up and PoC code circulating before the patch, the question of whether attackers have working details is mostly settled. Plan as if exploitation is happening.

Why This One Is Different

Most PHP emergencies are application bugs. You patch the plugin, and every other PHP site on the box is fine. A core interpreter flaw flips that. Every PHP app on the server shares the same exposure, including the ones nobody remembers deploying.

Three things make the blast radius worse than the CVSS score suggests.

The long tail can’t be patched. Plenty of production PHP still runs on 7.4 or 8.0 inside appliances, vendor products, and “temporary” internal tools. For those, there is no patch coming. The only options are upgrade, backport, isolate, or retire.

The fix ships through your supply chain, not PHP’s. Most servers don’t install PHP from php.net. They get it from a distro, a third-party repository, a container base image, or a hosting control panel. Each one rebuilds on its own schedule. Sansec specifically warned that users of Remi’s repository would not get the fix on release day. Your exposure window is however long your slowest packaging layer takes.

The usual mitigations are weak. Here’s how the main options stack up:

  • Disabling session.upload_progress.enabled. It’s the most widely shared workaround, and it lines up with the public write-up. But the researcher behind that write-up says it blocks only one of the two bugs, and that the other triggers in the multipart parser regardless. Aikido says it doesn’t protect against these bugs. Do it if you don’t use upload progress, but don’t count it as a fix.
  • Blocking multipart POSTs before PHP runs. This targets the parser path directly. Syhunt published a test kit for an Apache .htaccess rule that returns 403 on multipart/form-data POSTs. The README is honest about the limits: it breaks every multipart form, not just file uploads; it’s a header filter, not request normalization; and it only covers the routes it’s applied to. It also advises against blocking PHPSESSID at Nginx, which breaks sessions and doesn’t stop the parser. This is a reasonable stopgap for sites that don’t accept uploads.
  • WAF rules. Cloudflare has deployed rules for known exploit patterns to all plans, including free. Its CTO called them a stopgap. They also only help if your origin accepts traffic exclusively from Cloudflare. Regex-based multipart filtering is easy to bypass.
  • Containing the PHP process. Beaumont points to AppArmor or SELinux profiles that stop PHP from executing commands. That doesn’t stop the memory corruption, but it can turn “shell on the box” into a crashed worker. It’s worth doing regardless of this CVE.

The First 72 Hours

Last week I argued that the first 72 hours after a critical edge CVE is an incident, not a patching ticket. PHP2Shell is a clean test of that. Run it like one.

1. Find every PHP runtime, not just the ones you know about

Your CMDB will miss some. Ask the hosts directly.

# Package-managed PHP (Debian/Ubuntu and RHEL-family)
dpkg -l 'php*' 2>/dev/null | awk '/^ii/ {print $2, $3}'
rpm -qa 'php*' 2>/dev/null

# Any PHP binary on disk, including vendored and custom builds
find / -xdev -type f \( -name 'php' -o -name 'php-fpm*' -o -name 'php-cgi*' -o -name 'frankenphp' \) \
  -perm -u+x 2>/dev/null -exec sh -c 'echo "$1: $("$1" -v 2>/dev/null | head -1)"' _ {} \;

Then check container images. Scan your registry for base images with PHP, not just running containers. An old image redeployed next month is the same exposure.

2. Sort by exposure and supportability

Put every host in one of four buckets:

BucketExampleAction
Internet-facing, supportedPublic site on PHP 8.3Patch first, same day the build is available
Internet-facing, EOLVendor portal on PHP 7.4Isolate now. Upgrade, backport, or take offline
Internal, supportedIntranet app on PHP 8.4Patch in the normal emergency window
Internal, EOLLegacy reporting tool on PHP 8.0 or 7.xRestrict access, then plan the upgrade

The internet-facing EOL bucket is where this gets decided. Those hosts don’t have a patch path. Follow CERT-EU’s and the NCSC’s advice and pull them off the public internet until they do.

That advice deserves a second look. When two national cyber agencies tell organizations to consider taking systems offline before a patch even exists, that isn’t boilerplate. It’s a signal about how bad they expect the first few days to be.

3. Patch at the right layer

Know where each host’s PHP comes from, and watch that source, not just php.net. Distro security trackers, your container base image maintainer, and your hosting panel vendor will each publish on their own schedule. After patching, confirm the version actually running. A restarted php-fpm pool is not optional. The old binary stays in memory until you restart it.

4. Hunt for earlier exploitation

Patching closes the door. It doesn’t tell you who already walked through it. The leak was public a full day before the fix, the tool has a name, and PoC code was public before the patch. Assume someone tried.

Exploitation through an interpreter bug may not leave a useful trace in web server or WAF logs. Process lineage is the better signal. Look for PHP worker processes starting things they never should: shells, interpreters, download tools, and recon commands. Huntress and others are flagging the same pattern.

Here is a starting point in Sigma:

title: Shell or Download Tool Spawned by PHP Worker
status: experimental
description: Detects PHP runtimes spawning shells, interpreters, or network tools, a common post-exploitation pattern for PHP RCE such as PHP2Shell.
logsource:
  product: linux
  category: process_creation
detection:
  parent:
    # contains, not endswith: binaries are often versioned (php-fpm8.3)
    ParentImage|contains:
      - "/php-fpm"
      - "/php-cgi"
      - "/frankenphp"
      - "/httpd"
      - "/apache2"
  child:
    Image|endswith:
      - "/sh"
      - "/bash"
      - "/dash"
      - "/curl"
      - "/wget"
      - "/nc"
      - "/ncat"
      - "/python3"
      - "/perl"
      - "/base64"
  suspicious_cmdline:
    CommandLine|contains:
      - "/dev/tcp/"
      - "mkfifo"
      - "fsockopen"
  condition: parent and (child or suspicious_cmdline)
falsepositives:
  - Applications that legitimately shell out (image processing, PDF generation, cron wrappers)
level: high

Two notes on that rule. First, check your existing parent-process rules. Pentestit pointed out that a common SigmaHQ web shell rule doesn’t include php-fpm, php-cgi, or FrankenPHP as parents, so on an nginx plus php-fpm stack it would miss exactly this. Second, baseline before you alert. Some apps legitimately call convert or wkhtmltopdf. Tune them out by path, not by turning the rule off.

No EDR on your Linux web servers? Florian Roth released process-watcher, a small tool that logs every process a PHP worker starts, with its command line. It’s a reasonable stopgap while you fix the coverage gap.

Also check for new or modified .php files in web roots since October 20, unexpected outbound connections from web servers, and new cron entries or SSH keys for the web user.

The Leader Lens

The CVE isn’t the story. The ownership gap is.

Ask who owns PHP in your organization. The answer is usually “every team, a little bit.” The web team owns the app. Platform owns the base image. A vendor owns the appliance. Hosting owns the shared server. Nobody owns the interpreter. That’s how an organization ends up with a dozen PHP versions in production and no single person who can say which ones are internet-facing.

Use this to have that conversation once, while it’s concrete. Technical fact: a critical, unauthenticated RCE in PHP core, with no patch for anything older than 8.2. Business risk: some of our customer-facing systems run unsupported versions we can’t patch this week. Business impact: if one is compromised, we’re investigating a breach on a system we already knew was end of life. That last sentence is the one boards and regulators don’t forgive.

The ask isn’t more scanners. It’s a named owner for runtimes, and a rule that nothing internet-facing runs on an unsupported language version. For the vulnerability management basics behind that rule, see Foundations of Vulnerability Management.

Monday Morning

For practitioners:

  • Inventory every PHP runtime, including containers, appliances, and vendored builds. Record version, source, and exposure.
  • Until you can patch: turn off session.upload_progress.enabled where it’s unused, and block multipart POSTs before PHP on sites that don’t take uploads. Treat both as stopgaps.
  • Patch internet-facing supported hosts as soon as your packaging source ships the fix, then restart php-fpm and verify the running version.
  • Deploy a PHP-worker child-process detection, and confirm it covers php-fpm, php-cgi, and FrankenPHP.

For leaders:

  • Get a count of internet-facing hosts on PHP 8.1 or older. Decide today which ones get isolated.
  • Ask your hosting and appliance vendors for a written patch date. “We’re aware” is not a date.
  • Name an owner for language runtimes, so the next interpreter-level CVE has someone to call.

One Question

If PHP2Shell were a working exploit against your oldest internet-facing PHP server today, how long would it take you to find out?


Sources: PHP Foundation advance notice · Gina Peter Banyard · J4ck3LSyN write-up · Andrew Dorman · Kevin Beaumont · Syhunt php2shell-protection · UK NCSC · Cyber Security News · watchTowr FAQ · Sansec · Huntress · Patchstack · The Hacker News · SecurityWeek · Aikido · Pentestit

This is a developing story. I’ll update this post once PHP publishes the official affected and fixed versions.

comments powered by Disqus