PHP2Shell Explained: The PHP Vulnerability That Took Websites Offline

PHP2Shell (CVE-2026-109618 & CVE-2026-109619) is a pair of critical remote code execution vulnerabilities in PHP caused by unhandled memory cleanup during error bailouts. While many websites entered maintenance mode to apply patches, complete mitigation requires updating PHP to a supported release (8.2.35+, 8.3.36+, 8.4.27+, or 8.5.12+) and restarting all web server worker processes.
Harsh Mishra
October 23, 2026
PHP2Shell Explained

The cause was a single pair of bugs in PHP, nicknamed PHP2Shell. This is the story of what it is, why it set off such a scramble, and what you should actually do about it.

This piece runs in two lanes. The main road is plain English, no background needed. Partway down there is a clearly marked For the technically curious section where we open the hood and look at the real memory bug. Take whichever lane suits you.

Wait, did 70% of the internet actually break?

You have probably seen the line “PHP powers 70% of the web.” That part is roughly true: PHP runs behind about seven in ten websites whose server language is known, including most WordPress, Drupal, Joomla and Magento sites. But 70% exposed is very different from 70% went down.

What actually happened is that owners took their own sites offline on purpose, to patch safely. Many did it on official advice. The NSA in the US and ENISA in Europe both urged immediate action, and the NSA went as far as suggesting operators pull sites down if they could not patch in time. So most of the “outages” were deliberate pit stops, not servers getting hacked and falling over.

The scramble was about scale. Censys counted roughly 2.58 million internet-facing hosts running PHP. Qualys, scanning 12,000 organisations, found 167 million PHP installs, nearly three-quarters of them facing the internet, and about 71% on old end-of-life versions that will never get an official fix. In the first 12 hours, only around 199,000 had been patched. A lot of unlocked doors, and very few of them shut.

Date (2026) What happened
August Researchers at Calif, Wiz and OpenAI find the bugs and report them privately to PHP
17 October Amazon’s decoy network catches a real exploit attempt, four days before the public knew
20 October Details leak on forums; a proof-of-concept video is posted by accident. PHP announces an emergency release
21 October PHP ships fixes early (8.5.12, 8.4.27, 8.3.36, 8.2.35). NSA and ENISA warn. Attack code hits GitHub and attacks ramp up
22 October Sites sit in maintenance mode while teams patch; exploitation is confirmed in the wild

02So what even is PHP2Shell?

Think of PHP as the cook in the kitchen behind most websites. You, the site owner, write the recipe; PHP does the cooking and sends the finished plate out to visitors. PHP2Shell is not a bad recipe. It is a flaw in how the cook behaves when the kitchen suddenly runs out of space mid-dish.

That distinction is the whole point. Usually a security bug lives in someone’s recipe: a dodgy plugin or a sloppy line of code. This one lives in the cook. So even a flawlessly built website can be exposed, because the problem sits underneath it.

The name copies the famous Log4Shell bug from 2021. “Shell” is the ultimate prize: the ability to run your own commands on someone else’s server. Officially it is two bugs, CVE-2026-109618 and CVE-2026-109619, both rated a harsh 9.2 out of 10 (one firm called it a perfect 10). No password required, and nobody has to click anything.

03How the hack works, minus the jargon

Every PHP request has a memory budget. If a request tries to use too much, PHP slams on the brakes and bails out of whatever it was doing. The problem is how it bails.

Picture a clerk who is halfway through filing your paperwork when a fire alarm goes off, and bolts for the exit. On the way out they drop everything, but leave a sticky note on the desk: “customer’s files are in drawer 3.” Overnight, drawer 3 gets emptied. The next morning a different clerk reads the old note, trusts it, and opens drawer 3, except a stranger has quietly put their own files in there.

In plain wordsAn attacker deliberately sets off the “fire alarm” by running the server out of memory at a precise moment, so PHP skips its tidy-up and leaves a note pointing at a spot it no longer owns. A follow-up request slips the attacker’s own data into that spot, PHP trusts the stale note, and ends up carrying out the attacker’s instructions.

THE NORMAL FLOW

Request comes in,PHP does the work
PHP finishes andclears its workspace
Next visitor getsa clean slate
THE PHP2SHELL ATTACK

Attacker forces anout-of-memory crash
PHP bails out, skipsclearing up
Leftover pointer reused:attacker slips in

The same three steps, played straight and then abused.

Because one server process serves many visitors one after another, that leftover note can be picked up moments later, which is what makes it dangerous rather than just messy.

For the technically curious

04Under the hood

This section assumes you know your way around a web server.

The root cause: a bailout at the wrong moment

PHP aborts a failed request with the C functions setjmp() and longjmp(). setjmp() marks a safe return point; longjmp() leaps straight back to it from deep in the call stack, skipping every cleanup line in between. When PHP exceeds its memory_limit (128M by default) or hits certain fatal errors, it performs this bailout.

The bug is a timing window. A pointer is published before the risky step, and the line that clears it runs only after. If the bailout fires in between, the clear-up never happens, so a global keeps pointing at memory that is about to be freed. Simplified (not PHP’s real source):

bailout-windowC
// global, survives across requests
static char *current_session = NULL;

void handle_request(void) {
    if (setjmp(bailout_point) == 0) {
        current_session = allocate_request_memory(4096); // pointer published
        parse_input();          // may run out of memory -> longjmp()
        current_session = NULL; // cleanup: SKIPPED if longjmp() fired
    }
    free_all_request_memory();  // memory freed...
    // ...but current_session still dangles
}

The two CVEs

CVE-2026-109618, out-of-memory corruption. The OOM bailout leaves request data half-initialised; shutdown code then treats that garbage as valid and can be steered into running attacker-controlled code. On Apache mod_php with default settings, researchers pulled it off in roughly one request per attempt.

CVE-2026-109619, stale global state. A global reference outlives the memory it points to. Because workers are reused, the next request on the same worker reads that dangling pointer before anything resets it, a textbook heap use-after-free, and can turn it into code execution. This cross-request behaviour is exactly why patching alone is not enough: you must restart every PHP worker so no reused process keeps the vulnerable code in memory.

REQUEST 1 (attacker)
REQUEST 2 (attacker)

Build a big session,global points to it
Force out-of-memory:bailout skips cleanup
Memory freed, globalstill points to it
Same worker: fill thehole with crafted data
PHP follows the stalepointer to that data
Attacker code runs(remote code execution)
dangling pointer survives

CVE-2026-109619 use-after-free: six steps across two requests on the same worker.

Five demonstrated techniques, briefly

Researchers showed five concrete attacks. Three use PHP’s session upload-progress feature as the trigger, and that code runs while PHP is still parsing the request body, before your application executes, which is why an endpoint that only prints “OK” can still be hit. In rough order of nastiness, a successful attack can:

  • knock a worker over again and again (denial of service)
  • leak about 67 KB of raw server memory per hit, in a Set-Cookie: PHPSESSID header, which may hold passwords, tokens or other users’ data
  • read files the PHP process can see, such as config and database credentials, via a stale OPcache class-cache slot
  • run arbitrary commands as the PHP process, which is full remote code execution, when the pieces are chained together

Two honest caveats. Both CVEs carry high attack complexity: the attacker must win a race on memory layout and land a second request on the exact same worker. And code runs as the PHP process, not automatically as root. Serious, but not a guaranteed one-shot takeover every time.

05Who is actually at risk

Treat every unpatched PHP from 5.4 to 8.5 as affected. Fixes exist only for the four supported branches.

PHP branch Fixed version Status
8.5 8.5.12 Patched
8.4 8.4.27 Patched
8.3 8.3.36 Patched
8.2 8.2.35 Patched
8.1 & older No official fix End of life

Apache mod_php is ranked highest risk and should be patched first; PHP-FPM, php-cgi, LiteSpeed and FrankenPHP are all in scope too. One trap: the version php -v reports on the command line can differ from the one serving your website, so check the web-facing build.

06Am I affected? A 30-second check

Log into your server and run:

version-checkbash
php -v                   # web-facing PHP version
php-fpm -v               # if you use PHP-FPM
dpkg -l | grep -i php    # Debian / Ubuntu package version
rpm -qa | grep -i php    # RHEL / Alma / Rocky

If the number is below the fixed version for your branch, or it is 8.1 or older, assume you are vulnerable. Distributions often backport the fix without bumping the visible number, so check the changelog for the CVE IDs rather than trusting the version string alone. On shared hosting, just ask your host; most patched within a day.

07How to actually fix it

The only complete fix is to update and restart. No config tweak fully closes either bug.

  1. Update PHP to 8.5.12, 8.4.27, 8.3.36 or 8.2.35 (or your distribution’s patched package).
  2. Restart everything that loads PHP: Apache, all FPM pools, and rebuild your containers. A running worker keeps the vulnerable code alive until it restarts, and CVE-2026-109619 specifically abuses state carried between reused requests.
  3. On PHP 8.1 or older, upgrade to a supported branch. Do not stay on end-of-life PHP.

Patch, then restart every worker. The restart is the step most people miss.

Cannot patch this minute? These reduce risk but do not make you safe. PHP says to apply them together, set so applications cannot override them, then restart every worker:

stopgapini
session.upload_progress.enabled = 0   ; blocks the session attack paths
memory_limit = -1                     ; removes the OOM trigger (pair with a cgroup limit)
fatal_error_backtraces = 0            ; PHP 8.5 only
post_max_size = 8M                    ; shrink the memory-exhaustion surface

A web application firewall (Cloudflare, Imperva and others shipped rules) buys time as a virtual patch. If your app does not need file uploads, block multipart/form-data POSTs before they reach PHP.

After you patch, assume secrets may have leaked, since the bug can expose worker memory. Rotate passwords, API keys and tokens on internet-facing PHP, then watch for oddities: large multipart requests followed by memory errors or repeated HTTP 500s, malformed PHPSESSID cookies, surprise worker restarts, new admin users, or unexpected files.

If you are just a regular internet user

You cannot patch other people’s servers, so there is not much to do, but a few habits help. Keep your own devices updated. Do not be alarmed if some sites log you out or ask for a password reset this week, that is them rotating credentials after patching, which is a good sign. And use unique passwords with a password manager, so if one site did leak, the damage stops there.

Quick FAQ

+Why “PHP2Shell”?

It copies the Log4Shell naming style. “Shell” means gaining command-line control of the server.

+Did AI really find it?

AI assisted the human researchers (OpenAI’s model helped); it was not found by AI alone.

+I run a small WordPress blog, what do I do?

On managed or shared hosting, confirm your host has patched (most did within a day). On your own server, update PHP and restart it. WordPress, Drupal, Joomla and Magento are all affected because the flaw is in PHP, not in them.

Not sure if your stack is exposed?

TWO99 runs fast security and performance audits for PHP and WordPress sites.

Talk to our team →

Key Takeaways

  • Mass Maintenance, Not Mass Outages: The sudden drop of major websites around October 21, 2026, was primarily due to site owners intentionally putting systems into maintenance mode to patch safely following urgent warnings from agencies like the NSA and ENISA.

  • Underlying Engine Flaw: Nicknamed PHP2Shell, the vulnerabilities (CVE-2026-109618 and CVE-2026-109619) exist within the PHP engine itself rather than application code or plugins, making even flawlessly built websites vulnerable.

  • Mechanism of Exploitation: The bugs exploit PHP’s setjmp() and longjmp() memory bailout routines during out-of-memory (OOM) events, leaving stale pointers/global references active that permit remote code execution (RCE) and memory leakage across reused worker processes.

  • Essential Remediations: Complete resolution requires updating PHP to a patched release (8.2.35+, 8.3.36+, 8.4.27+, or 8.5.12+) and restarting all PHP processes/web server workers so old processes do not carry vulnerable code in memory.

  • End-of-Life Hazard: Over 70% of scanned internet-facing PHP installations are running unsupported branches (PHP 8.1 and older) that will receive no official security fix, requiring a full version upgrade.

Harsh Mishra
Content Development Lead

A content and digital strategy professional with 6+ years experience and a strong foundation in technical writing, SEO, and data-driven content systems. Experienced in building research-backed content, brand strategy, Technical content and optimizing workflows. Skilled at blending storytelling with technology, with hands-on expertise across digital marketing, analytics, website development, and performance optimization. Focused on creating scalable content frameworks that support long-term growth rather than short-term visibility.

Expertise Areas:
Technical & SEO content, digital marketing strategy, performance marketing, Brand Storytelling, Content Strategy, Community engagement, AI & Technology Communication,WordPress development, analytics-driven growth

Latest Articles

© 2026 TWO99. All Rights Reserved

An ISO/IEC 27001:2022 and ISO 9001:2015 certified organization