PHP2Shell: what to do about CVE-2026-109618 and CVE-2026-109619

PHP2Shell (CVE-2026-109618 and CVE-2026-109619): unauthenticated RCE in the PHP core, already exploited. Fixed versions, mitigation, finding every exposed PHP.

· #attack surface · #PHP2Shell · #vulnerability · #PHP · #active exploitation · #shadow IT

PHP2Shell is the nickname for two vulnerabilities in the PHP interpreter, CVE-2026-109618 and CVE-2026-109619, both scored 9.2 on CVSS v4.0. Both allow unauthenticated remote code execution on servers that handle web requests with PHP. The fixed versions are 8.5.12, 8.4.27, 8.3.36 and 8.2.35, released on October 21, 2026.

Updated on October 22, 2026. This is a moving story, and the numbers below will age fast.

Why this one is different

A critical PHP bug is nothing new. Almost every week one shows up in some CMS, plugin or framework written in the language. PHP2Shell sits a floor below all of that. It lives in the interpreter itself, in the code that handles each HTTP request before control ever reaches the application.

That changes who is exposed. It does not matter whether the site runs WordPress, Laravel, Magento or a homegrown system from 2012. If the PHP answering the request is a vulnerable version, the way in exists. The PHP team ranked the findings among the most severe in the project's history, according to the analysis published by Wiz, one of the three teams that found the problem, together with OpenAI and Calif.

And PHP is everywhere. W3Techs puts it on 70.3% of the websites whose server-side language can be identified. Of those, 28.9% still run version 7 and 7.9% version 5, branches the project no longer patches.

What each CVE does

Both flaws come from the same mechanism. When PHP runs out of memory or hits a fatal error in the middle of a request, it abandons the work with a direct jump out of the current context, longjmp(), which the PHP team calls a bailout. Some parts of the code did not expect that interruption and left internal state half built.

CVE-2026-109618 is out-of-memory corruption. If the bailout fires while internal request data is only partially initialized, the cleanup routine that runs next reads that memory as if it were valid. The official advisory says several memory exhaustion strategies trigger the condition reliably.

CVE-2026-109619 is stale global state. PHP keeps global pointers that temporarily point into request memory. In some scenarios they are not cleared at the end, or get repopulated after being cleared, and keep pointing at memory that was already freed. The next request handled by the same process can use that pointer before normal initialization runs. It is a cross-request use-after-free, described in GHSA-6wmf-4rv5-p3rp.

The remote trigger cited most often is session upload progress (session.upload_progress), enabled by default since PHP 5.4. It updates session state while PHP is still reading the body of a multipart POST, before the application even enters the picture. According to Imperva, three of the five known exploitation techniques go through it. watchTowr stresses that this is one confirmed path, not the only one.

We are not going to walk through the exploit chain here. For defenders, what matters fits in one sentence: an attacker with no account sends a crafted request to any endpoint that accepts POST and can walk away with code execution on the server.

One detail helps calibrate the risk. Exploitation is high complexity, because the next request has to land on the same process and fill the freed memory in just the right way. When it does not line up, the process crashes instead of running code. That slows down a single targeted attempt. It does nothing against a mass scan that tries thousands of times.

Who is exposed

Every PHP installation that serves web requests, under any SAPI: PHP-FPM, Apache with mod_php, php-cgi, FrankenPHP and LiteSpeed. Qualys and watchTowr single out mod_php as the most urgent case, because Apache calls the request shutdown routine even when request startup failed. The attack completes before any application code runs.

PHP branch Fixed version Status
8.5 8.5.12 official patch
8.4 8.4.27 official patch
8.3 8.3.36 official patch
8.2 8.2.35 official patch
8.1, 8.0, 7.4 no release minimal source backport, or your distribution's package
7.3 and older, back to 5.4 no fix treat as vulnerable

Watch the version number on Linux distributions. Red Hat, Ubuntu, Fedora, AlmaLinux and others ship the backport without changing the upstream version, so a php -v showing 8.1 may be fixed while one showing a hand-compiled 8.2.30 is certainly not. Your distribution's advisory is what decides.

Then there is the PHP nobody remembers. On October 22, Palo Alto Networks said every version of PAN-OS and Panorama is affected, with no fix yet. Fortinet is reviewing 12 products and Cisco 31 products and cloud services. Firewalls, router panels, management consoles, backup appliances: a lot of equipment carries an embedded PHP that shows up in no software inventory.

Timeline

PHP2Shell timeline, October 2026. October 17: an Amazon honeypot records the first exploitation attempt. October 18: ThreatSensor picks up the first sightings of CVE-2026-109618. October 20: details leak before the embargo, watchTowr reproduces both flaws and the first public PoC for CVE-2026-109619 appears. October 21: PHP releases 8.5.12, 8.4.27, 8.3.36 and 8.2.35, the UK NCSC urges taking offline anything that cannot be fixed, and Cloudflare ships WAF rules. October 22: active exploitation of both CVEs, PAN-OS affected, 313 public PoCs and 133 sightings, still not in KEV.

Sansec had predicted mass exploitation within 15 minutes of the patch. That turned out to be optimistic. The attacks started before the patch.

What ThreatSensor shows

ThreatSensor, CSURFACE's public exploitation intelligence database, already tracks both CVEs with everything collected so far. The snapshot from October 22:

CVE-2026-109618 CVE-2026-109619
PoC repositories on GitHub 313 10
Exploitation in the wild confirmed, 133 sightings not detected so far
First signal sighting on Oct 18 PoC published on Oct 20
Attacker interest high high
CISA KEV catalog not yet not yet
Ransomware association no no

Two things stand out.

The first is speed. Less than 48 hours after the patch, CVE-2026-109618 had piled up more than 300 public repositories: PoCs, scanners, Docker labs and detection rules. Wiz wrote that frontier AI models substantially lowered the barrier to turning the flaw into an exploit, and the amount of public code on day one fits that.

The second is KEV. The flaw has been exploited since before the patch and is still not in the CISA catalog. Anyone who waits for KEV to prioritize a fix is, right now, behind 133 observed attacks. CISA needs evidence to add an entry, and evidence takes days. That is why the queue cannot depend on the catalog alone.

What to do now

In order. The order matters.

  1. Preserve evidence before you touch anything. PHP and web server logs, current configuration, suspicious files. If the server is already compromised, patching wipes the trail and leaves the intruder inside.
  2. Update to the fixed version for your branch, or to your distribution's fixed package. Unsupported branches need the project's backport or an LTS vendor. Updating is the only complete fix, and every source agrees on that.
  3. Restart every PHP worker. PHP-FPM, Apache, LiteSpeed. The stale state lives in the process, and an old process stays vulnerable with a new binary on disk.
  4. Prioritize internet-facing mod_php, then the other exposed SAPIs, then everything else.
  5. Look for signs of compromise on servers that were exposed since October 17: new web shells, unexpected cron jobs, new accounts, odd child processes of PHP, outbound connections that were not there before.
  6. Whatever cannot be fixed today comes off the internet or goes behind access control. That is the NCSC recommendation.

Temporary mitigation, if you cannot update right away

These settings close part of the paths. None of them replaces the patch, and watchTowr warns that .ini changes do not cover the whole surface.

; turns off the trigger used by three of the five known techniques
session.upload_progress.enabled = Off

; PHP 8.5
fatal_error_backtraces = Off

On PHP-FPM, pm.max_requests = 1 makes each process exit after one request, which keeps stale state from carrying over to the next. The performance cost is high and needs testing. Imperva also suggests opcache.enable = 0 as a temporary measure, again with testing first. Turning off session.upload_progress does not fully address CVE-2026-109618, because the out-of-memory corruption sits in the Zend core.

A WAF helps until the patch lands. Cloudflare, Imperva and others have already published rules for the known vectors. A new variant gets past an old rule, so treat the WAF as a bridge.

Signals to look for in your logs

The question most companies cannot answer today

Every security team got the same order this week: patch PHP. That order assumes a list. Which servers run PHP, on which version, exposed to what.

The list that exists is the official inventory, and it covers what someone remembered to register. The PHP that gets exploited this week lives somewhere else. The 2019 campaign microsite nobody shut down. The staging environment that went up with an integration and kept a public IP. The corporate blog on a host that marketing bought with a company card. The domain that came along with an acquisition. The appliance panel IT never thought of as a PHP server.

That is shadow IT, and it is the part of the surface that weighs most in a flaw like PHP2Shell, because it is exactly the part running the oldest versions. The 7.9% of sites still on PHP 5 are not anyone's main server.

Worse than the forgotten asset is the one nobody knows they do not know about. Someone knew the forgotten asset at some point and can be reminded. The unknown one went live through a path that never touched security, and no internal question reaches it, because nobody knows to ask.

In two cases documented by CSURFACE, a mid-sized financial institution had 160 external assets in its official inventory and discovery found 271. A B2B SaaS startup was monitoring 85, and there were 570. The cybersecurity coordinator at one of Brazil's largest companies summed up the effect in one sentence: finding out we were monitoring only 15% of our real attack surface.

In a company like that, fixing 100% of the list fixes 15% of the problem.

How CSURFACE customers get ahead of this kind of problem

For companies running CSURFACE, the question "where do we have exposed PHP, and on which version" has an answer before the flaw gets a name. The work that answers it runs all the time, so the week starts with the fix instead of the spreadsheet.

Full view of the surface

Continuous discovery maps the external surface from what is public: domains, subdomains, certificates, IP blocks, DNS records, group companies. The starting point is the company's name. The list the company handed over is used for comparison, to show what was missing from it. Every asset found is fingerprinted by technology, which includes PHP and its version when the server reveals it, the SAPI when it can be inferred, and appliances that carry embedded PHP.

Shadow IT and what nobody knew existed

That is where the old microsite, the staging box with a public IP, the appliance panel and the acquired domain show up. An asset found without an owner becomes an item with context: where it is, when it appeared, what it runs, who most likely answers for it. CSURFACE tells the customer the forgotten server exists before an attacker knocks on it.

Exploitation intelligence crossed with the real inventory

ThreatSensor follows every CVE with an exploitation signal, and the threat intel layer crosses that signal with what discovery already knows. When a CVE such as CVE-2026-109618 starts showing up in attacks, the customer's assets running the affected technology move to the top of the queue on the exploitation signal. No waiting for KEV, no dependence on CVSS.

Fast detection, with proof

Continuous validation confirms, non-destructively, whether the asset is actually exposed in the conditions it is in. The queue stops being "every server with PHP" and becomes "these, which have an open path right now", with evidence for the infrastructure team to act on and for the manager to report to the board. After the patch, the same validation confirms the fix took.

The asset that shows up tomorrow gets covered too

Fixing everything this Thursday does not protect you from the server someone spins up next Tuesday from an old Docker image. Continuous monitoring catches that server the day it appears. The annual pentest would only see it next year.

PHP2Shell will get fixed, the way Log4Shell and React2Shell did. The next flaw this size will find the same unanswered question at every company that does not know what it has on the internet.

If you want to know today where your company's PHP is, including what is on no list at all, the free preliminary analysis from CSURFACE gives you the first picture of your external surface.

Frequently asked questions

What is PHP2Shell?

It is the nickname for two vulnerabilities in the PHP interpreter, CVE-2026-109618 and CVE-2026-109619, disclosed on October 21, 2026 with a CVSS v4.0 score of 9.2. Both allow unauthenticated remote code execution, triggered by an HTTP request before any application code runs.

Which PHP versions are vulnerable?

Every version before 8.5.12, 8.4.27, 8.3.36 and 8.2.35 in their respective branches. Branches 8.1, 8.0 and 7.4 only got a source backport. Older versions, back to 5.4, should be treated as vulnerable with no official fix. For Linux distribution packages, check your distribution's advisory, because a backport may keep the old version number.

Is PHP2Shell being exploited already?

Yes. Amazon recorded an exploitation attempt on October 17, four days before the patch. ThreatSensor shows confirmed exploitation of CVE-2026-109618, with 133 sightings as of October 22, and more than 300 public PoC and tooling repositories. For CVE-2026-109619, exploitation in the wild has not been detected yet, but a public PoC has been out since October 20.

Does turning off session.upload_progress fix it?

It lowers the risk without fixing it. The setting removes the trigger for three of the five known techniques, but the out-of-memory corruption in CVE-2026-109618 sits in the PHP core and has other paths. The only complete fix is to update and restart every worker.

My site runs WordPress (or Laravel, or Magento). Am I exposed?

If the PHP running underneath is a vulnerable version, yes. The flaw is in the interpreter and is reached before the application runs, so the framework or CMS makes no difference. Updating WordPress does not fix PHP2Shell. Updating PHP does.

How do I find every server with PHP my company has on the internet?

The internal inventory answers for what was registered. For what is published without a record, such as test environments, old microsites, acquired domains and appliances with embedded PHP, you need to look from the outside, starting from what is public about the company. That is what asset discovery does, and it is the starting point of continuous threat exposure management.

Want to see this on your own surface?

Book a demo