365Digital

PHP2Shell Explained: The Black October PHP Vulnerability and What Site Owners Must Do Now

PHP2Shell vulnerability and Patches

On Wednesday, 21 October 2026, something unusual happened across the web. Government websites in France, the Netherlands, Finland and Denmark went dark on purpose. Japanese airline ANA, railway operator JR West and bank MUFG suspended some webpages. In the UK, council sites in Edinburgh, Bristol and Oxford went offline, and nearly three dozen government services were unavailable the next day (Amplix, Stockpil).

Nobody had hacked them. They were racing to patch two critical flaws in PHP itself, the language that runs roughly 70% of all websites, including every WordPress, Drupal and Joomla site. The flaws are called PHP2Shell, and the week they landed is now being called Black October.

If you run a website on PHP, this guide tells you exactly what happened, how the attack works, how to check whether you are exposed, and how to fix it today. In a hurry? Jump to the fix.

TL;DR: PHP2Shell at a glance

  • What: Two critical remote code execution flaws in the PHP engine: CVE-2026-109618 and CVE-2026-109619.

  • Severity: CVSS v4.0 9.2 each (rated by PHP). Unauthenticated: no login, no user interaction.

  • Impact: An attacker can run code on your server, steal data, plant backdoors, or read passwords and API keys straight out of server memory.

  • Affected: PHP 5.4 through 8.5.11. Any PHP site serving web requests, whatever app runs on top.

  • Fixed in: PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35 (released 21 Oct 2026, 14:00 UTC).

  • Status: Exploit tools and write-ups are public. Exploit attempts began before disclosure and climbed into the millions within hours.

  • Your action: Update PHP (not just WordPress), restart PHP, then check for signs of compromise.

Not sure where to start? Contact our team and we will check your server and walk you through the patch, step by step.

What is PHP2Shell?

PHP2Shell is the name for two memory-safety vulnerabilities in the core PHP interpreter, disclosed on 21 October 2026 by researchers at Calif, OpenAI and Wiz. Both let an attacker who sends crafted HTTP requests execute code on the server with the web server's privileges, without logging in (Wiz, CISA).

CVE-2026-109618

CVE-2026-109619

PHP's title

Remote Code Execution via OOM corruption

Remote Code Execution via stale global state

GitHub advisory

GHSA-w8hw-w9fx-j79w

GHSA-6wmf-4rv5-p3rp

What goes wrong

An out-of-memory error interrupts PHP while request data is half built; cleanup then treats the broken data as valid

A fatal error leaves internal state pointing at memory from a previous request; the next request on the same worker uses it after it was freed

Severity

CVSS v4.0 9.2

CVSS v4.0 9.2

Confirmed impact

Full RCE on Apache mod_php with default settings, before any app code runs; RCE on PHP-FPM via app code paths

Use-after-free and worker crash confirmed; RCE demonstrated on a real-world app on mod_php

Source: PHP Foundation.

Three things make PHP2Shell different from the plugin bugs WordPress owners are used to:

  • It is in PHP, not in your app. Wiz notes that even a plain "Hello World" script on an affected PHP version can be vulnerable. Keeping WordPress and plugins updated does not help here.

  • It leaks secrets, not just code execution. Wiz demonstrated reading chunks of live server memory, which can hold passwords, session tokens, API keys and certificates belonging to other visitors' requests. Wiz compares this to Heartbleed.

  • It reaches back a decade. Every PHP version since 5.4 is affected by at least one of the bugs (Wiz).

The score you may have seen floating around, CVSS 10.0, came from the leak on 20 October and is wrong. PHP rates both flaws 9.2 on CVSS v4.0; the NVD separately lists 9.8 on the older CVSS 3.1 scale (Brandefense).

Why it's being called "Black October"

"Black October" is not an official name. It took off after a widely shared X post at 03:42 UTC on 22 October described the previous 48 hours as the worst in cybersecurity history (SecurityToday). PHP2Shell was the headline act, but it was not alone.

The attacks started before the patch existed

Cloudflare CEO Matthew Prince (@eastdakota) shared figures on X: thousands of exploit attempts across Cloudflare's network in the 10 hours before the announcement, tens of thousands in the first 45 minutes after it, hundreds of thousands within two hours, and millions after that (Cryptonews). Those are attempts, not confirmed break-ins, but they show how fast attackers moved.

Amazon's threat intelligence team went further. It saw an exploitation attempt against a honeypot on 17 October, four days before public disclosure, and concluded that PHP2Shell was being broadly exploited in the wild (The Register, Tenable). Security firm Hadrian reported exploitation at scale from 21 October, mostly through PHP's session upload-progress path, and Cloudflare saw attackers tweaking payloads to slip past its firewall rules (daily.dev).

Governments said: patch, or pull the plug

The US National Security Agency posted an unusually blunt warning on X. It said the flaws "often provide a direct path to the server's file system or database" and advised taking systems offline if an immediate update was not feasible (Newsweek). It followed with a formal advisory, Critical Patches Recommended for PHP Vulnerabilities, telling organisations to inventory PHP systems, apply patches and isolate anything they could not fix (HackerNoon).

CISA, the UK's NCSC and CERT-EU gave the same advice: patch now, and take PHP systems offline or off the public internet until you can (ProjectDiscovery). The NCSC also urged checks for backdoors left by attackers. In the Netherlands, the national NCSC took its own website offline as a precaution (Techzine).

Organisation

Response

CISA (US)

Alert urging immediate updates to 8.5.12, 8.4.27, 8.3.36 or 8.2.35 (CISA)

NSA (US)

Patch, or take systems offline

CERT-EU

Security Advisory 2026-018, issued 20 Oct

UK NCSC

Patch, isolate, and hunt for backdoors

Governments in France, Netherlands, Finland, Belgium, Germany, Czech Republic, Denmark

Temporarily took sites offline while patching (Stockpil, Amplix)

Finland's Valtori

Took government public services offline (HackerNoon)

An important nuance: these sites went offline as a precaution. Newsweek noted there was no evidence that US federal government websites had been compromised by PHP2Shell.

The rest of the 48 hours

PHP2Shell landed in the middle of a pile-up of unrelated incidents, which is what turned a bad week into "Black October":

  • GitLab CVE-2026-110264: an unauthenticated RCE rated CVSS 10.0, in code dating back to 2014. Fixed in 19.5.1, 19.4.3 and 19.3.6 (daily.dev).

  • LiteLLM 1.107.0: a poisoned release of a hugely popular AI library shipped a credential stealer through PyPI and Docker for about two hours.

  • Railway: the hosting platform reported possible access to customer environment variables, paused deploys and revoked API tokens (GPTunneL).

  • Zeabur: an environment-variable breach affecting 321,810 accounts, followed by a shutdown announcement (Root-Nation).

  • eMudhra: a compromise at the Indian certificate authority (BusinessToday).

  • Node.js fixed ten flaws including a high-severity Brotli decoder issue, and stolen UpdraftCentral keys were used to backdoor WordPress sites.

Some of these attacks had been running for months before they surfaced (SecurityToday). For PHP site owners, though, PHP2Shell is the one that needs action today.

How AI found a bug hiding since PHP 5.4

The weakness behind PHP2Shell is old. What changed in 2026 is that frontier AI models made it practical to turn that weakness into a reliable exploit.

A 22-year paper trail

  • 2004: PHP security researcher Stefan Esser found the first PHP memory-limit remote vulnerability, the ancestor of this bug class (Calif).

  • 2020: PHP bug #78876 reported that long multipart variables could trigger out-of-memory errors. It looked harmless at the time.

  • 2024: A security audit of PHP funded by Germany's Sovereign Tech Agency, organised by OSTIF and carried out by Quarkslab, led a PHP core developer to the first signs of the out-of-memory problem. No path to code execution was proven, and the fix stalled over hard trade-offs (PHP Foundation).

The PHP Foundation is unusually candid about that stall. It calls the delay "a structural failure", caused by the security team's consensus-based decision process and a lack of resources, and says it has since changed how such decisions are made.

Calif, OpenAI and "Patch the Planet"

In July 2026, the PHP Foundation brought PHP into OpenAI's Patch the Planet programme. Security firm Calif started auditing PHP on 30 July. Within days, researcher Ryan Austin, working with OpenAI's GPT-5.6 Sol, found the first out-of-memory interruption that led to remote code execution against WordPress (Calif).

On 5 August he tweeted only a cryptographic hash of the finding, a way of proving priority without revealing anything.

Calif reported the bug to PHP on 11 August, shared a working proof of concept on 14 August, and PHP confirmed it the next day. OpenAI's own team independently reported the same root cause on 11 August and sent further attack vectors on 18 September (PHP Foundation). OpenAI President Greg Brockman said the company led a two-month coalition to coordinate the fix (KuCoin News), and OpenAI described the discovery as "one of the most impactful security issues in recent memory" (Forbes).

Wiz's independent discovery

Google-owned Wiz found the bugs independently on 19 August using its Wiz Atlas tool, Google's Gemini 4 Argon and GPT-5.6 Sol. It had unauthenticated RCE against Drupal the next day and WordPress the day after, and reported to PHP on 24 August (Wiz). Wiz says Gemini 4 Argon made a major contribution to finding the bug, building the exploit, detecting attacks and validating the patch.

Wiz's researchers ranked the findings among the most severe ever found in PHP, "arguably in software history", and compared PHP2Shell to Heartbleed (2014) and Log4Shell (2021) as a turning point.

Why AI mattered here

Calif is clear that it used no special harness or private models for the first discovery. The researcher already knew PHP's vulnerability history and pointed the model at a specific theory: that relatives of Esser's 2004 bug might still be lurking. The model then helped trace code paths, generalise the pattern into a reusable search, and find more variants (Calif).

Wiz makes the bigger point. Memory bugs like these need exploits adapted to each target's PHP version, configuration and memory layout. That used to take a world-class team months. With frontier models, Wiz says, a single researcher did it in a week, and adapted working exploits across applications in hours (Wiz). The same capability is available to attackers, which is why the patch window is now measured in hours, not weeks.

Technical deep dive: how PHP2Shell works

This section is for developers and sysadmins. If you only need the fix, skip ahead.

The root cause: a bailout that skips cleanup

When PHP hits a fatal error, such as running out of the memory allowed by memory_limit, it does not unwind neatly. It uses the C function longjmp() to jump straight out of whatever it was doing. Any code that was halfway through setting something up never finishes, and the cleanup that should have followed is skipped.

In a long-running PHP worker that serves many requests, that leaves global state pointing at memory that has already been freed. The next request on the same worker can then trust that stale state. Calif summarises the pattern as: publish some state, do work that can fail, then commit or roll back. A fatal error during the middle step skips the last one (Calif).

Step 0: running PHP out of memory on demand

To exploit this, an attacker needs to trigger an out-of-memory error at a precise moment. PHP's limits should prevent that, but Calif found two ways around them:

  1. post_max_size only checks the declared length. PHP compares post_max_size with the Content-Length header, not with the bytes it actually reads. A chunked HTTP/1.1 or length-less HTTP/2 multipart request can therefore carry far more data.

  2. Empty file uploads multiply memory use. A file part with filename="" is not counted against max_file_uploads, yet PHP still creates six $_FILES entries for it. With deeply nested field names such as files[a][b][c], each tiny part balloons into many internal hash table allocations. Hundreds of them can exhaust the default 128 MB memory limit while the request body stays under the default 8 MB post_max_size.

This is why the exploit body can be tiny. One write-up puts the CVE-2026-109619 payload at roughly 450 bytes, too small for a simple WAF size rule to catch (DEV Community).

The four exploitable primitives

Wiz and Calif describe at least four distinct ways to turn that crash into control. PHP groups all of them under the two CVEs, and its patch fixes the underlying pattern so other variants are closed too (Wiz).

Primitive

Where in PHP

What breaks

Demonstrated

Half-built hash table bucket

_zend_hash_str_add_or_update_i, during request variable parsing

Element counters are bumped before the key is allocated; teardown later reads a garbage bucket

RCE against arbitrary scripts on Apache mod_php, PHP 7.3+ (Calif)

Session upload-progress stale state

php_session_rfc1867_callback, before modules are activated

Session ID and session data left pointing into a freed heap

Pre-auth RCE on WordPress, Drupal, Joomla; memory disclosure (Wiz)

Fatal-error backtrace use-after-free

EG(last_fatal_error_backtrace)

The stored backtrace survives the freed heap and is touched by the next request

Pre-auth RCE on Drupal (Wiz)

OPcache type confusion

zend_accel_script_persist and the map_ptr frontier

Local and shared slot counters disagree; another worker reuses a slot as the wrong type

Pre-auth RCE on WordPress across workers (Wiz)

Walkthrough: the two-request session chain

The session upload-progress path is the one attackers use most, according to Hadrian, so it is worth seeing step by step.

PHP2Shell two-request chain

PHP2Shell two-request chain, session upload-progress path (simplified from the Calif write-up).

  1. Request A is a large multipart upload. Because session.upload_progress.enabled is on by default, PHP starts tracking the upload in a session before its modules are fully activated, and stores pointers to request memory in session globals.

  2. Later in the same request, the attacker's nested fields push PHP over memory_limit. PHP bails out with longjmp().

  3. On Apache mod_php, request shutdown still frees the request's memory, but skips the session module's cleanup because modules were never marked active. The worker survives, holding stale pointers.

  4. Request B lands on the same worker. It is a multipart form with a session ID and the upload-progress field, but no file, so the normal session reset never runs.

  5. Upload-progress cleanup now reads the stale session ID and destroys the stale session value, both sitting in memory the attacker has refilled with their own data. That gives memory corruption, and from there code execution.

The crash in Request A is harmless on its own. The danger is that Request B reaches the same worker before anything resets the stale state (Calif).

Why mod_php is worst, and why PHP-FPM is not safe

On mod_php, Apache's handler runs request shutdown even after a startup failure and keeps the worker alive, so the stale state is reachable before any of your application code runs. PHP-FPM behaves differently: a startup failure kills the worker, which blocks that particular path.

Calif found a second route for PHP-FPM. If the out-of-memory error is triggered later, while the application is calling unserialize() or session_start() (WordPress reaches this through its normal maybe_unserialize() calls), the unserializer's bookkeeping is left dangling and the FPM worker survives. A follow-up upload-progress request then reuses that bookkeeping, giving the attacker control over where PHP writes a pointer. That is application-dependent RCE on PHP-FPM behind Nginx, which Calif demonstrated on video. The PHP Foundation confirms RCE on FPM through application-level code paths.

How PHP runs

Exposure

Apache mod_php

Highest risk. Application-independent RCE demonstrated with default settings

PHP-FPM (Nginx, Apache proxy)

Vulnerable. RCE confirmed via common app code paths

php-cgi, FrankenPHP, LiteSpeed (lsphp)

In scope per PHP; less public analysis

PHP CLI scripts not serving web requests

Not the target of these attacks

Sources: PHP Foundation, Sophos, Bitdefender.

The Heartbleed part: reading server memory

Wiz also showed a leak that needs no code execution at all. In the same upload-progress path, PHP can treat the stale session ID pointer as a real string and URL-encode whatever now sits in that memory into the PHPSESSID cookie it sends back. The attacker receives a chunk of live worker memory, which may include other users' passwords, tokens and API keys. It works even if the application never calls session_start() (Wiz).

This is why rotating secrets belongs in your response plan even if you find no sign of a break-in.

What actually got popped

Calif confirmed pre-authentication RCE against WordPress 7.1.2, Drupal 11.4.3, Joomla 6.1.4, MediaWiki 1.46.2, Roundcube 1.7.4, Magento 2.4.9, phpMyAdmin 5.2.3, Nextcloud 35.0.1, Laravel 13.11, Symfony 8.1 and WHMCS. Wiz did the same against the official wordpress:latest, drupal:latest and joomla:latest container images.

Honest limits

The exploits are not trivial. CVE-2026-109619 needs the attacker's requests to reach the same worker, so servers with many workers lower the success rate per attempt. CVE-2026-109618 also requires defeating ASLR, and early public proofs of concept were unreliable (Bitdefender). But attackers can simply send more requests, and AI makes adapting exploits cheap. Treat these limits as friction, not protection.

Am I affected?

If your website runs on PHP and has not been updated since 21 October 2026, assume yes. That includes almost every WordPress, WooCommerce, Drupal, Joomla, Magento, Laravel and cPanel-hosted site.

Version by version

PHP branch

Support status

Vulnerable

Fixed in

8.5

Active

Below 8.5.12

8.5.12

8.4

Active

Below 8.4.27

8.4.27

8.3

Security fixes until 31 Dec 2027

Below 8.3.36

8.3.36

8.2

Security fixes until 31 Dec 2026

Below 8.2.35

8.2.35

8.1, 8.0, 7.4

End of life

All

No official release. PHP published minimal source backports; distros and LTS vendors ship patched packages

5.4 to 7.3

End of life

All

No fix. Isolate and migrate

Sources: CISA, Sophos, TuxCare, php2shell.uk.

TuxCare cites a count of roughly 884,000 internet-facing hosts still advertising PHP 8.1 or older, which get nothing from php.net directly. If you are one of them, your path is in the next section.

How to check the PHP your website actually runs

The PHP your website uses is not always the PHP you see on the command line. Check the web runtime.

  • Shared hosting with cPanel: open MultiPHP Manager to see the version for each domain. Then ask your host directly whether their PHP builds include the fixes for CVE-2026-109618 and CVE-2026-109619.

  • Your own server: create a temporary file containing <?php phpinfo(); in your web root, open it in a browser, note the version and Server API (Apache 2.0 Handler means mod_php; FPM/FastCGI means PHP-FPM), then delete it immediately.

  • Command line: php -v for the CLI, and php-fpm8.3 -v (or your version) for FPM.

The version-number trap

Linux distributions often patch PHP without changing the upstream version number. Ubuntu 24.04's fixed package still reports PHP 8.3.6, even though it includes both fixes (teramont). The Sury/ondrej PPA does the same for its 8.1, 8.0 and 7.4 builds (computingforgeeks).

So "8.3.6" is not automatically vulnerable, and "8.3.36" is not the only safe answer. On Debian and Ubuntu, check the package changelog for the CVE IDs:

zgrep -E 'CVE-2026-10961[89]' /usr/share/doc/php8.3-cli/changelog.Debian.gz

On RHEL, AlmaLinux and Rocky:

rpm -q --changelog php-cli | grep -E 'CVE-2026-10961[89]'

If the CVE IDs appear, your package is patched. If nothing comes back, it is not.

Want a second pair of eyes? Contact us with your hosting setup and we will confirm whether your PHP is patched and guide you through each step.

The fix: patch PHP today

Updating PHP is the only complete fix. PHP's own release notes say plainly that "updating is the only safe choice" (php-src 8.4.27). Updating WordPress core, plugins or themes does not fix PHP2Shell, because the flaw is in the runtime underneath them.

Before you start: take a full backup (files and database) and, if you can, test on a staging copy first. Then patch production the same day.

Option 1: shared hosting or managed WordPress

You usually cannot update PHP yourself on shared hosting; your host does it at server level. Sansec makes the same point: the fix is a server-level PHP update that a site cannot apply from its own code (Brandefense).

  1. Open a support ticket and ask: "Have your PHP builds been patched for CVE-2026-109618 and CVE-2026-109619 (PHP2Shell)? Which PHP versions on my account are covered?"

  2. In cPanel's MultiPHP Manager, switch each domain to a patched supported version (8.3 or 8.4 is a safe choice for most WordPress sites). GoDaddy reports that cPanel backported the fix to its 7.4, 8.0 and 8.1 packages too (Brandefense).

  3. If your host cannot confirm a patch, put the site behind Cloudflare (the free plan includes PHP2Shell rules) and apply the mitigations in the next section while you wait.

Option 2: VPS or dedicated server

Ubuntu and Debian (official packages):

sudo apt update
sudo apt install --only-upgrade 'php*'

Distro

Fixed package

Advisory

Ubuntu 26.04 LTS

php8.5 8.5.4-0ubuntu1.5

USN-8948-1

Ubuntu 24.04 LTS

php8.3 8.3.6-0ubuntu0.24.04.13

USN-8948-1

Ubuntu 22.04 LTS

php8.1 8.1.2-1ubuntu2.28

USN-8948-1

Ubuntu 20.04 and older

php7.4 7.4.3-4ubuntu2.29+esm5 (via Ubuntu Pro ESM)

USN-8948-2

Debian 13 (trixie)

php8.4 8.4.27-1~deb13u1

DSA-6574-1

Debian 12 (bookworm)

php8.2 8.2.35-1~deb12u1

Debian security

RHEL 9

php:8.2 module to 8.2.35

RHSA-2026:87072

Sources: teramont, Brandefense.

Sury / ondrej PPA: the PPA ships 8.5.12, 8.4.27, 8.3.36 and 8.2.35, plus backported builds for older branches (8.1.34-9, 8.0.30-25, 7.4.33-31) that keep the old version string. If you run PHP 7.x from the PPA, make sure your upgrade command includes it; a php8* pattern will skip it (computingforgeeks).

RHEL, AlmaLinux, Rocky, Remi:

sudo dnf upgrade 'php*'

Then restart every PHP process. A patched file on disk does nothing while old code is still loaded in memory (Armis):

sudo systemctl restart php8.3-fpm   # use your version
sudo systemctl restart apache2      # or httpd; required for mod_php

Finally, re-run the changelog check from the previous section to confirm the CVE IDs are present.

Option 3: Docker and Kubernetes

Pulling a new image is not enough. Rebuild and redeploy every container that runs PHP.

  1. Bump your base image to a fixed tag (for example the official php:8.3.36 or php:8.4.27 variants, or the patched wordpress, drupal and joomla images).

  2. Rebuild with docker build --pull --no-cache so you do not reuse a cached vulnerable layer.

  3. Redeploy and confirm with docker exec <container> php -v (or check the image changelog for distro-based images).

Many self-hosted tools shipped emergency releases the same day: for example the Pterodactyl panel moved its image to PHP 8.3.36 (GitHub) and Coolify to PHP 8.4.27 (GitHub). Check every PHP-based tool you self-host.

Option 4: stuck on PHP 8.1, 8.0, 7.4 or older

These branches are end of life and get no new release from php.net. Your options, best first (php2shell.uk, TuxCare):

  1. Upgrade to PHP 8.3 or 8.4 now. If 8.4 is too big a jump, 8.3 is supported until the end of 2027. Avoid moving to 8.2, which reaches end of life on 31 December 2026.

  2. Use a vendor backport: Ubuntu Pro ESM, Debian LTS, Red Hat, cPanel, the Sury PPA, or a commercial extended-support vendor such as TuxCare, which has shipped 7.4 builds on most Linux platforms.

  3. Build from source using PHP's minimal backport branches for 8.1, 8.0 and 7.4. These fix only these two CVEs; the branch stays unsupported.

  4. PHP 5.4 to 7.3: there is no backport. Take the site offline or off the public internet, apply every mitigation below, and migrate.

Upgrading an old WordPress or custom PHP site feels risky? That is normal: plugins and old code can break on a new PHP version. Contact us and we will help you plan the upgrade and test it on staging before it touches your live site.

If you cannot patch today: temporary mitigations

These settings reduce risk while you wait for a patch. None of them is a fix, and some have real side effects. Apply them, then keep pushing to patch.

Setting

What it blocks

Side effect

session.upload_progress.enabled = 0

The confirmed session path for CVE-2026-109619 (the one attackers use most)

Session-based upload progress bars stop working

memory_limit = -1, set so apps cannot override it

The out-of-memory trigger for CVE-2026-109618

One request can use all the server's RAM; pair it with a per-worker memory cap (cgroup or container limit)

fatal_error_backtraces = 0 (PHP 8.5 only)

The backtrace path for CVE-2026-109619

Fatal errors lose their backtrace

pm.max_requests = 1 in the PHP-FPM pool

State carried between requests on one worker

Large performance cost; every request gets a fresh worker

Low post_max_size (8M if you have no uploads, 32M with) plus body, multipart part, header and nesting limits at the web server or proxy

Reduces the memory pressure attackers need

May break large uploads

Sources: Qualys, Sevalla, runZero, SOCRadar, Calif.

Calif's own short version: on PHP-FPM, disable session upload progress and set memory_limit to -1; on mod_php, set memory_limit to -1. Then, in its words: "But seriously: patch."

Where to put the settings

Setting them with php_admin_* stops applications from overriding them at runtime.

PHP-FPM pool (for example /etc/php/8.3/fpm/pool.d/www.conf):

php_admin_flag[session.upload_progress.enabled] = off
php_admin_value[memory_limit] = -1
; optional, heavy performance cost:
; pm.max_requests = 1

Apache with mod_php (virtual host or main config):

php_admin_flag session.upload_progress.enabled off
php_admin_value memory_limit -1

Shared hosting: use cPanel's MultiPHP INI Editor to set session.upload_progress.enabled to Off. You may not be allowed to change memory_limit to -1; ask your host.

Restart PHP-FPM or Apache afterwards, then confirm:

php -i | grep -E 'session.upload_progress.enabled|memory_limit'

(Check the web runtime too, through a temporary phpinfo() page, since the CLI may read a different php.ini.)

A web application firewall buys time

Cloudflare deployed PHP2Shell rules for every plan with its WAF on, including Free, from 03:02 UTC on 21 October, about nine hours before disclosure. It built a new "full transaction detection" capability that looks at both the request and the response, so it can also catch memory leaking out in the reply (Cloudflare). Fastly, Google Cloud Armor, Akamai, Imperva and Vercel shipped protections too (Fastly, Google Cloud, Vercel).

Cloudflare's own leadership called these rules "a STOPGAP only" (The Hacker News). They only see traffic that passes through Cloudflare (attackers who find your origin IP go around them), and attackers are actively mutating payloads to slip past.

The emergency brake

If you cannot patch or mitigate, do what governments did: switch the site to a static, read-only version, put it behind a login or VPN, or take it offline until it is fixed. That is the NSA's advice, and several national agencies followed it on their own sites.

Have I already been hacked? Detection and indicators

Patching closes the door. It does not remove anyone who already walked through it. Because attempts began on 17 October, four days before the patch, review activity from at least 15 October onward.

PHP2Shell runs below your application, so WordPress security plugins and app logs may show very little. Wiz advises watching for the side effects instead (Wiz). No vendor had published confirmed file hashes or IP indicators at the time of writing; Bitdefender and Huntress both said they had no IOCs to share yet (Bitdefender, Brandefense). So look for behaviour.

1. Suspicious requests in access logs

  • Large or malformed multipart POST requests to any .php URL, especially with very many parts or deeply nested field names

  • Chunked requests with no Content-Length header

  • Request bodies are often not logged, so look at request size and frequency instead

2. Error log patterns

  • Bursts of "Allowed memory size of ... bytes exhausted" fatal errors

  • Clusters of HTTP 500 responses and execution timeouts

  • Session warnings such as illegal session IDs

  • Unexplained PHP worker crashes or restarts

grep -c "Allowed memory size" /var/log/apache2/error.log
grep "Allowed memory size" /var/log/php*-fpm.log | tail -50

3. Odd cookies in responses

Unusually large or garbled PHPSESSID cookies sent by your server are a sign of the memory disclosure bug being triggered (Wiz).

4. What the attacker did next

Once inside, attackers behave the same way they always do. These are the strongest signals (Sygnia, Armis):

  • Web server or PHP processes (apache2, httpd, php-fpm, php-cgi, lsphp) starting shells (sh, bash), scripting tools (python, perl), downloaders (curl, wget) or reconnaissance commands (id, whoami, uname, hostname)

  • Outbound connections from the web server to unfamiliar addresses, especially reverse shells

  • New or modified PHP files, particularly in upload or cache folders

  • New admin users, unfamiliar plugins, or new scheduled tasks (cron or WP-Cron)

Quick checks on a Linux server:

# PHP files changed since 15 October in your web root
find /var/www -name '*.php' -newermt '2026-10-15' -ls

# PHP files inside upload folders (should normally be none)
find /var/www -path '*uploads*' -name '*.php'

# Child processes of PHP and web server workers
ps -ef --forest | grep -E -A3 'php-fpm|apache2|httpd'

# WordPress: list admin users and verify core files
wp user list --role=administrator
wp core verify-checksums

5. Assume secrets may have leaked

Even with no signs of code execution, the memory disclosure bug could have exposed anything the PHP worker held in memory. If your server was exposed and unpatched, plan to rotate: database passwords, API keys, payment gateway keys, SMTP credentials, cloud access keys, and WordPress salts in wp-config.php.

Found something odd and not sure what it means? Contact us. We will review your logs with you and tell you whether it looks like an attack and what to do next.

If you find a compromise: recovery checklist

Work through this in order. Do not try to "clean" a hacked server in place; attackers usually leave more than one way back in.

  • Isolate the server (take it offline or block public traffic) and preserve web server and PHP logs before changing anything. Huntress gives the same advice (Brandefense).

  • Rebuild from clean sources: a fresh server or container with patched PHP, your code from version control or a backup taken before 15 October, and a reviewed database.

  • Rotate every secret the PHP worker could read: database passwords, API keys, payment gateway keys, SMTP, cloud keys, and WordPress salts.

  • Reset admin passwords and review all admin accounts; enable two-factor login.

  • Remove persistence: unknown plugins, cron jobs, mu-plugins, .htaccess changes, and PHP files in upload folders.

  • Check connected systems the server could reach (databases, internal APIs, cloud accounts) for unusual access (Sygnia).

  • Report it where required. In India, cyber incidents involving covered entities must be reported to CERT-In within six hours; customer data exposure may also trigger obligations under India's data protection law. Other countries have their own rules.

  • Monitor closely for a few weeks after recovery.

Hardening so the next one hurts less

PHP2Shell will not be the last engine-level bug. The PHP Foundation says AI-assisted research has already led to 15 PHP CVEs since 1 July and well over 100 invalid or duplicate reports (PHP Foundation). Expect more patches, faster.

  • Move off mod_php to PHP-FPM. It was the highest-risk setup here.

  • Turn on automatic security updates for PHP packages, or use a host that patches the runtime for you, and know how to reach them in an emergency.

  • Stay on a supported PHP version. Plan the move from 8.2 before it reaches end of life on 31 December 2026.

  • Block PHP execution in upload folders and keep file permissions tight.

  • Disable dangerous functions your apps do not need: exec, shell_exec, system, passthru, proc_open.

  • Put a WAF in front of your site and hide your origin server's IP address.

  • Keep secrets out of reach: short-lived credentials, separate keys per service, and a written rotation routine.

  • Keep tested backups off the server, and know your restore time.

The controversy: a leak, an embargo break, and a mystery blog

The plan was a clean coordinated release on 22 October. It fell apart in the final 48 hours, and that is part of why site owners had so little warning.

The leak. Around 15:00 UTC on 20 October, the two CVE IDs started circulating on forums and social media with a wrong release time and a wrong CVSS score of 10.0. No technical details leaked, but PHP brought its pre-announcement forward to 19:30 UTC and moved the release up a full day, to 14:00 UTC on 21 October (PHP Foundation).

The video. Around 20:00 UTC, Calif mistakenly published a video of its exploit working against several targets. It was deleted, but copies spread on social media and sped up the development of public proofs of concept. Mitigation advice shared with a few critical infrastructure providers may also have leaked. PHP says none of the proofs of concept it inspected before release were functional (PHP Foundation).

The embargo break. At 07:41 UTC on 21 October, more than six hours before the release, Chainguard published patched container images. Like other distributors, it had received the fix in advance. The PHP Foundation criticised the move, saying it let attackers study the fix in binary form while everyone else waited. Chainguard CEO Dan Lorenc said on LinkedIn that his company had independently found the same bugs by asking a frontier AI model to find bad vulnerabilities in PHP (404 Media).

The mystery blog. A post titled "There isn't an easy exploit for this PHP vulnerability" by an "Elias Taylor" went viral and was picked apart on Hacker News, where readers noticed the domain had only just been registered and nobody could say who the author was (404 Media). Reassuring content from unknown sources during an active attack wave deserves suspicion. Stick to the primary sources listed at the end of this article.

The lesson for site owners: you cannot count on a quiet week of warning before a patch. Have a process to apply emergency PHP updates within hours.

What PHP2Shell means for the AI era

The bug class was known in 2004, glimpsed in 2020 and flagged again in 2024. It became an emergency in 2026 because AI made the hard part, turning a fragile memory bug into a working exploit across many targets, fast and cheap.

That cuts both ways:

  • Defenders got there first this time. Calif, OpenAI and Wiz used AI to find, exploit, detect and help patch the flaws, and Cloudflare had protections live before disclosure.

  • Attackers have the same tools. Exploit attempts began four days before the patch, and Cloudflare saw payloads being adjusted in real time to dodge its rules.

  • Open source maintainers are stretched. The PHP Foundation says security work on a language that runs much of the web still depends on a small group of funded developers and volunteers, and has asked companies, hosts and governments to sponsor that work (PHP Foundation). OpenAI has restated a $1 billion subsidised commitment to give defenders access to its security tools (PPC Land).

For website owners, the practical takeaway is simple: the time between "bug disclosed" and "bug exploited" is now hours. Knowing exactly what runs your site, who patches it, and how fast they can do it is no longer optional.

Need help patching PHP2Shell? Talk to us

Everything in this guide can be done yourself. But if you are not sure which PHP your site really runs, your host is slow to reply, or an upgrade might break an old plugin, it helps to have someone who has done it before beside you.

Contact our team and we will:

  1. Check your exposure: identify your PHP version, how it runs (mod_php, PHP-FPM, LiteSpeed) and whether your packages actually contain the fixes.

  2. Walk you through the patch, DIY-style: clear steps for your exact setup, whether that is cPanel, a VPS, Docker or managed WordPress, so you or your developer can apply them correctly. Or we can do it with you on a call.

  3. Apply safe stopgaps if you cannot patch immediately, tuned so they do not break your site.

  4. Plan the upgrade from PHP 7.4, 8.1 or 8.2 to a supported version, tested on staging first.

  5. Look for signs of compromise in your logs, files and admin accounts, and help you rotate secrets if needed.

Contact us now and tell us your website address and hosting setup. We will reply with your next steps.

Frequently asked questions

What is PHP2Shell?

PHP2Shell is the name for CVE-2026-109618 and CVE-2026-109619, two critical flaws in the PHP engine disclosed on 21 October 2026. Both let an unauthenticated attacker run code on servers running unpatched PHP, and one also leaks server memory.

Which PHP versions are affected and which are fixed?

PHP 5.4 through 8.5.11 are affected. Fixed versions are 8.5.12, 8.4.27, 8.3.36 and 8.2.35, or distribution packages whose changelog lists both CVE IDs. PHP 8.1 and older get no official release, only source backports and vendor packages.

Is WordPress affected? Does updating WordPress fix it?

WordPress sites are affected because WordPress runs on PHP, and Wiz demonstrated RCE against the official WordPress image. Updating WordPress, plugins or themes does not fix it. You or your host must update PHP.

How do I know if my hosting provider has patched PHP?

Ask them directly whether their PHP builds include the fixes for CVE-2026-109618 and CVE-2026-109619, and which versions on your account are covered. A version number alone can mislead, because many hosts and distros backport fixes without changing it.

My server says PHP 8.3.6. Am I still vulnerable?

Not necessarily. Ubuntu 24.04's patched package still reports 8.3.6. Check the package changelog for the CVE IDs (see "The version-number trap" above).

What if I'm stuck on PHP 7.4 or 8.1?

Upgrade to PHP 8.3 or 8.4 if you can. If not, use a patched package from your distro or an extended-support vendor, apply the temporary mitigations, and plan the upgrade. PHP 5.4 to 7.3 has no fix at all.

Does Cloudflare or another WAF protect me?

Partly. Cloudflare's free and paid WAF rules block known exploit patterns, but Cloudflare calls them a stopgap, attackers are changing payloads, and rules only cover traffic routed through the WAF. Patch anyway.

Is PHP2Shell being exploited in the wild?

Amazon, Cloudflare, Hadrian and watchTowr reported exploitation attempts, starting four days before disclosure and reaching millions within hours. Attempts are not the same as confirmed compromises, but the exploit tools and write-ups are public, so treat any unpatched server as at risk.

Is PHP2Shell in CISA's Known Exploited Vulnerabilities catalog?

At the time this article was published, neither CVE had been confirmed as added to CISA's KEV catalog, although CISA issued an alert urging immediate patching. We will update this article if that changes.

Has CERT-In issued an advisory?

At the time this article was published, we had not found a CERT-In advisory specific to PHP2Shell. Indian organisations should still patch immediately, following CISA, NSA, NCSC and CERT-EU guidance.

Why is it called Black October?

Security watchers used "Black October" for the cluster of major incidents around 20 to 22 October 2026: PHP2Shell, a CVSS 10.0 GitLab flaw, a poisoned LiteLLM release, the Railway and Zeabur breaches, and more. It is a nickname, not an official term.

Did AI really find this bug?

Yes, with human experts steering. Calif used OpenAI's GPT-5.6 Sol, and Wiz used Google's Gemini 4 Argon, GPT-5.6 Sol and its own Wiz Atlas tool. The underlying weakness had been partly known for years; AI made it practical to prove it exploitable.

Status at time of publishing

As of 23 October 2026: patches are available for all supported PHP branches; exploit attempts are widespread; neither CVE had been confirmed as added to CISA's Known Exploited Vulnerabilities catalog; and no CERT-In advisory specific to PHP2Shell had been found. This article will be updated as official guidance changes.

Sources and further reading

Official advisories and releases

Original research

Vendor guidance and analysis

News coverage