PHP2Shell (CVE-2026-109618 and CVE-2026-109619)
Two bugs inside PHP, the language behind most websites, let a stranger run their own commands on a web server. The attacker needs no password and no account, only carefully built web requests.
The PHP project scores each bug 9.2 out of 10 on CVSS v4.0, the usual scale for how severe a flaw is, and 9.2 counts as Critical. CISA, the US government's cyber defence agency, lists both as exploited by attackers.[1, 3, 5]
9.2out of 10Critical
CVSS v4.0
The PHP project gives each bug this score.[1, 19, 20]
NVD, the US government's vulnerability database, gives its own CVSS v3.1 scores of 9.8 Critical for CVE-2026-109618 and 8.1 High for CVE-2026-109619.[19, 20]
- No Login NeededThe attacker needs no account and no password, only web requests.[5]
- Exploited Before the FixAmazon saw attempts from 17 October, four days before PHP shipped the patches.[8]
- On CISA's KEV ListCISA added both bugs on 26 October and gave US federal agencies until 29 October to fix them.[3]
Fixed In
- 8.5.12
- 8.4.27
- 8.3.36
- 8.2.35
PHP shipped the fixes on 21 October 2026. PHP 8.1 and older get no routine updates.[2]
The Short Version
If you read nothing else, read these four lines.
- What It Is
- Two bugs in PHP itself that let an attacker who has not signed in run code on the web server.
- Who Is Affected
- Any web server whose PHP has not been updated to 8.5.12, 8.4.27, 8.3.36, 8.2.35 or a patched package. Apache with mod_php is the most exposed.[2, 5]
- How Serious It Is
- The PHP project rates both bugs Critical. Attackers are using them, and CISA gave US federal agencies three days to fix them.[1, 3]
- What to Do
- Update PHP, restart every PHP worker, then look for signs that someone got in first.
What PHP Is
When you open a web page, a web server takes your request, the way a waiter takes an order in a restaurant. On a PHP site the waiter hands the order to PHP, the kitchen.
PHP cooks the page from the site's recipe, which is the website app such as WordPress, Drupal or an online shop. It takes the ingredients from the database, the pantry.
PHP is very common. W3Techs counts it on about 7 in 10 websites whose server language it can identify, and iTWire reports the same share.[9, 10]
The fault is in PHP itself, so every app that PHP runs is exposed, whatever the app is. That is why updating WordPress or its plugins does not fix it. PHP itself has to be updated.
Where PHP Sits
The picture follows one visit, from the visitor to the database. The bug sits in PHP, in the middle of the chain, and the bracket shows what code running there can reach.
- VisitorThe dinerYou, in a web browser
- Web ServerThe waiterApache or nginx
- PHPThe kitchenCooks each pageThe bug is here
- Website AppThe recipeWordPress or Drupal
- DatabaseThe pantryThe site's stored data
Code running in the kitchen can reach the recipes and the pantry.
Bug One: The Half-Written Order
The first bug is CVE-2026-109618, which CISA lists as PHP Memory Corruption Vulnerability. It works like an order that is only half written down when the kitchen gives up on it.
Every visit starts with PHP filling in a form about the request. The form says who sent it, what they sent and which files came with it.
The attacker sends a specially shaped upload, so that PHP runs out of memory part-way through filling in that form. PHP then takes an emergency exit straight to its clean-up step.[1, 11]
The clean-up step trusts the form. But half of the form still holds leftovers that the attacker arranged, and following those leftovers runs the attacker's code.
With Apache and mod_php, this happens before the website's own code starts, so the site's own security never gets a say. The PHP Foundation says the attack works there with default settings.[1]
The Half-Written Order
The picture shows the form as a set of slots. The first three were filled in properly, the fourth is where memory ran out, and the last two still hold leftovers when the clean-up step reads them.
The Form PHP Fills In for One Request
- Sender
- Headers
- Upload 1
- Memory Full
- Leftover Junk
- Leftover Junk
Emergency exit, straight to clean-up
Clean-Up Step
Trusts every slot on the form
It reads the junk as real, so the attacker's code runs.
- Filled in by PHP
- Where memory ran out
- Left over, arranged by the attacker
Step Through Bug One
Press Next to follow the request through PHP one step at a time. The current step is drawn bolder, and Back goes over the steps again.
- Attacker Sends the request
- PHP Fills in the form
- Clean-Up Step Tidies up after
- Step 1 of 4, from Attacker to PHP. A Shaped Upload Arrives
- Step 2 of 4, on PHP. Memory Runs Out
- Step 3 of 4, from PHP to Clean-Up Step. Emergency Exit to Clean-Up
- Step 4 of 4, on Clean-Up Step. Clean-Up Trusts the Leftovers
Step 1 of 4 The attacker sends one specially shaped upload. PHP starts filling in its form about the request, as it does for every visit.
Bug Two: The Key Card That Still Works
The second bug is CVE-2026-109619, which CISA lists as PHP Stale Internal Request-State Vulnerability. It works like a hotel key card that still opens a room after the guest has left.
PHP reuses the same worker, a running program that handles requests, for request after request. It is like a hotel reusing its rooms for one guest after another.
The attacker makes one request crash while PHP is cleaning up after it. PHP hands that request's memory back but keeps a note that still points to it.[5, 6]
The attacker then fills that spot in memory with their own data. When a second request lands on the same worker, PHP follows the old note and runs the attacker's data as if it were its own.
This kind of bug is called a use-after-free. It only works when both requests land on the same worker.[5, 16]
The Key Card That Still Works
The picture shows one worker handling two requests, one after the other. Both lead to the same spot in memory, which the attacker refilled in between.
One PHP Worker
Request A
The attacker forces a crash during clean-up
Later
Request B
Same worker, same old note
A's note still points here
B follows the stale note
A Spot in Memory
Handed back, then refilled by the attacker
The attacker's data runs as if it were PHP's own.
Step Through Bug Two
Press Next to follow the two requests through one PHP worker. The current step is drawn bolder, and Back goes over the steps again.
- Attacker Sends the requests
- PHP Worker Handles one request after another
- A Spot in Memory Held request A's data
- Step 1 of 5, from Attacker to PHP Worker. First Request Arrives
- Step 2 of 5, from PHP Worker to A Spot in Memory. Spot Handed Back, Note Kept
- Step 3 of 5, from Attacker to A Spot in Memory. The Spot Is Refilled
- Step 4 of 5, from Attacker to PHP Worker. Second Request Arrives
- Step 5 of 5, from PHP Worker to A Spot in Memory. B Follows the Stale Note
Step 1 of 5 Request A reaches a PHP worker. The attacker built it to make PHP crash while it cleans up after the request.
What Attackers Get Once In
Either bug leads to the same place. The steps below run from the first request to a foothold that lasts, as the researchers describe them.
Each step needs the one before it.
- It starts with web requests that need no login.
- The attacker's code runs as the web server's PHP worker, with the same access the site has.[5]
- They can take the site's secrets, such as database passwords, API keys and cloud account keys. Elastic Security Labs says collecting credentials and secrets files is almost always one of the next steps.[7]
- They can leave a back door, called a web shell, that keeps working after PHP is patched.[7, 15]
- Dream Research reported attackers chaining PHP2Shell with a Linux kernel flaw to take full control of the server as root. Unit 42 says it checked the same tools and confirmed the result.[6]
Why It Is a Big Deal, and the Other Side
Several things make these bugs serious, and a few things limit them. Both sides are below, so you can judge the risk to your own servers.
How Far the Bug Reaches
This is the Tech Stacks topic's layer stack for a PHP website. The bug is in the runtime layer, so every app that PHP runs above it is exposed, whichever app it is.
- ApplicationExposed
WordPressDrupalJoomlaMagentoMediaWikiOnline shopsEvery PHP app on the server is exposed, because PHP runs its code.
- Framework and LibrariesExposed
LaravelApps built with a PHP framework are exposed in the same way.
- Web and App ServersCarries the Request In
Apache HTTP ServerPHP-FPMThe web server hands each request to PHP. With mod_php, PHP runs inside Apache's own processes, which makes it the easiest target.[1, 5]
- RuntimeThe Bug Is Here
PHPBoth bugs are in PHP itself, so the fix is to update PHP.
- Operating SystemNot Reached Alone
LinuxThese bugs alone do not reach the operating system. Dream Research reported a chain with a Linux kernel flaw that does, and Unit 42 confirmed it.[6]
Why It Is Serious
These are the reasons the bugs made the news.
- There is no login and no click. CrowdStrike, as reported by iTWire, says it verified that one anonymous request was enough on Apache with mod_php.[9]
- It sits under every PHP app, including WordPress, Drupal, Joomla, Magento and MediaWiki.
- Unit 42 says Palo Alto Networks sees over 22.6 million exposed instances, meaning systems reachable from the internet, that are potentially vulnerable.[6]
- Attackers moved before the fix. Amazon says its honeypots, decoy servers set up to attract attackers, logged an attempt on 17 October, four days before PHP shipped the patches.[8]
- iTWire reports OpenAI's president, Greg Brockman, saying the flaw had sat in PHP for about 14 years.[9]
- PHP 8.1 and older get no routine updates. The PHP project published minimal fixes for 7.4, 8.0 and 8.1 for people who build PHP themselves from its source code.[2, 11]
What Limits It
These are the reasons not every PHP server fell at once.
- Apache with mod_php is the easiest target, because bug one works there before any website code runs.[1, 5]
- PHP-FPM, the other common way to run PHP, needs extra conditions. The PHP Foundation confirmed attacks on it through paths in the website's own code.[1, 5]
- The first public exploits were narrow. Rapid7 says each worked only on one mix of operating system, PHP version and web server, and none was broadly reliable.[5]
Timeline
The problem was first spotted in 2024, but most of what happened came in the second half of October 2026. Each row is one event, with the date it happened.
Late October at a Glance
Each event sits on its own day between 17 and 29 October. The bracket marks the days when attackers were already trying the bugs and no fix existed yet.
Dates without a year are in 2026.
A Quarkslab audit of PHP leads a PHP core developer to the first signs of the memory problem. A possible attack was suspected, but no concrete way in was found.[1]
Amazon's honeypots record attempts to exploit the bugs, the earliest that Amazon saw.[8]
The CVE ids leak early with a wrong score of 10.0, but no technical details leak with them. PHP brings its release forward by a day.[1]
Fixes ship in PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35, a day earlier than planned. CISA issues an alert the same day.[2, 4]
Australia takes cyber.gov.au and other federal websites offline overnight as a precaution while it works to reduce the risk.[9]
Public proof-of-concept exploits appear, which are demonstrations that an attack works. Rapid7 says each works only on one mix of operating system, PHP version and web server.[5]
CISA adds both CVEs to its KEV list, with a due date of 29 October for US federal agencies.[3]
Palo Alto Networks reports attacks on PAN-OS management interfaces that are open to the internet.[6]
How People Are Mitigating It
Updating PHP is the only complete fix. The other steps close the known ways in or limit the damage until you can update.[2, 5]
Work down the steps in order. The first two are the fix, and the rest buy time or catch what got through.
| Step | What to Do |
|---|---|
| Update PHP | Update PHP itself to 8.5.12, 8.4.27, 8.3.36, 8.2.35 or later, or install the patched package from your Linux distribution. CISA advises taking PHP systems offline if you cannot update yet, or if they run PHP 8.1 or older.[2, 4] |
| Restart Every PHP Worker | Restart every PHP worker after you update or change a setting. A worker that keeps running holds on to the old code and settings, so a restart after an update is standard practice, and the PHP project asks for one after each settings change.[2] |
| Use the Stopgaps | If you cannot update today, apply the settings in the next table. They close the routes that are known, not every route. |
| Add Virtual Patches | OWASP describes a virtual patch as a rule in front of the site that spots and blocks attempts on a known flaw without changing the flawed code. CISA says a web application firewall (WAF) may give some protection until you patch. Palo Alto Networks lists Threat ID 543004 as a rule for its own firewalls.[4, 6, 22] |
| Hunt for Compromise | Run the hunts in Hunting for It below. If you find anything, standard practice is to change the database passwords and API keys as well. Quiet logs do not prove a server is safe.[5, 7] |
| Keep Management Interfaces Off the Internet | Admin pages, such as a firewall's management interface, should be reachable only from an internal network. CISA requires this of US federal agencies for firewalls and other network devices, and Unit 42 reports attacks on PAN-OS management interfaces left open to the internet.[6, 21] |
These settings shrink the known routes in until you can update. The PHP project says none of them makes a server safe on its own, so update as soon as you can.
| Stopgap | What It Does | Where to Set It |
|---|---|---|
session. | Turns off session upload progress, which closes a confirmed route to bug two.[2] | In php.ini, an FPM pool or the server's configuration, so it applies before PHP reads the request. Setting it from the site's code with ini_set() or in .user.ini is too late.[2, 5] |
fatal_ | On PHP 8.5 only, turns off backtraces for fatal errors, which blocks the confirmed backtrace route to bug two.[2] | Set by the administrator, then restart every worker. |
memory_ | Removes PHP's own memory limit, so reaching it can no longer set off bug one. A real shortage of memory still can, so pair it with the size limits below.[2, 5] | Set by the administrator where sites cannot change it, such as php_ in the FPM pool or the Apache configuration. |
post_max_size and upload_ | Caps how much one request can send. PHP suggests 8M (8 megabytes) where a site takes no uploads and 32M where it does, with upload_ below post_max_size.[2] | In php.ini. |
| Request Limits in Front of PHP | Limits the size of each request, the number of form fields, upload parts and headers, and how deeply the fields nest. Where a site never takes multipart uploads, the kind that carry files, block them before they reach PHP.[2, 5] | At the web server, the proxy or the WAF in front of PHP. |
Not RLIMIT_AS or RLIMIT_DATA | Do not use these operating system memory limits in place of the settings above. PHP and Rapid7 warn that they can cause the very memory failure that bug one needs.[2, 5] | Leave them out of this fix. |
Am I Affected?
It depends on how you use PHP. Pick the situation that fits you, and for a server its PHP branch, to see what to do. With nothing picked, every answer shows.
I Just Use Websites
There is nothing to do. The flaw is on the servers that run websites, not on your computer or phone.
My Site Is on a Hosting Plan
Ask your host whether the PHP on your server has been updated and its workers restarted. Updating WordPress or its plugins is not enough. The email below asks for you.
I Run the Servers
Check the PHP version with php -v, update PHP, restart every PHP worker, then hunt for signs of compromise. A patched package from a Linux distribution can keep an older version number, so check its security notice too.[2, 5]
- PHP 8.5Fixed in 8.5.12Update to PHP 8.5.12 or later, or to the patched package from your Linux distribution.
- PHP 8.4Fixed in 8.4.27Update to PHP 8.4.27 or later, or to the patched package from your Linux distribution.
- PHP 8.3Fixed in 8.3.36Update to PHP 8.3.36 or later, or to the patched package from your Linux distribution.
- PHP 8.2Fixed in 8.2.35Update to PHP 8.2.35 or later, or to the patched package from your Linux distribution.
- PHP 8.1 or OlderNo routine fixThere is no routine update. The PHP project published minimal fixes for 7.4, 8.0 and 8.1 for people who build PHP themselves from its source code, and CISA advises taking PHP 8.1 and older offline.[2, 4, 11]
- Not SureCheck firstRun
php -von the server to see its version, then pick that branch here. On a hosting plan, ask your host instead.
Hunting for It
If you run PHP servers, look for signs that someone got in before you patched. Rapid7 warns that a quiet log does not prove a server is safe, so run each of these hunts even if nothing alerted.[5]
Each hunt comes in four tools, with the record it reads and what must be switched on first. The Defender XDR tables fill only on servers onboarded to Defender for Endpoint, which runs on Linux too.[12, 13, 14]
A Web Server or PHP Worker Starting a Shell or Download Tool
A PHP worker serving web pages has no reason to start a shell, the program that runs typed commands. Elastic Security Labs calls this the clearest sign that an attack worked, and CISA names it as a sign to watch for.[4, 7]
A download tool such as curl or wget started the same way may be an attacker pulling in their own tools after getting in.[4, 7]
- A Hit Shows
- The web server or a PHP worker started a shell or a download tool, with the time and the command it ran.
- It Does Not Prove
- Some sites start these programs on purpose, so compare each command with what the site is meant to do. An empty result does not prove a server is safe either, as Rapid7 warns.[5]
Defender XDRKQLSees It Directly
This table fills only on Linux servers onboarded to Defender for Endpoint. It names the parent and the grandparent, so a download started through a shell still shows.
// Shells and download tools that a web server or PHP worker started, directly or through a shellDeviceProcessEvents
| where Timestamp > ago(30d)
| where FileName in~ ("sh", "bash", "dash", "zsh", "curl", "wget")
| extend Parent = tolower(InitiatingProcessFileName), GrandParent = tolower(InitiatingProcessParentFileName)
| where Parent startswith "php" or Parent in ("apache2", "httpd", "nginx")
or GrandParent startswith "php" or GrandParent in ("apache2", "httpd", "nginx")
| project Timestamp, DeviceName, AccountName, GrandParent, Parent, InitiatingProcessCommandLine, FileName, ProcessCommandLine
| order by Timestamp descSentinelKQLSees It Directly
The Sentinel query loads from the article's query file, with what it needs switched on. Open the Query File
VelociraptorVQLSees It Directly
The Velociraptor query loads from the article's query file, with what it needs switched on. Open the Query File
SplunkSPLSees It Directly
The Splunk query loads from the article's query file, with what it needs switched on. Open the Query File
New or Changed Scripts in the Web Root
The web root is the folder the site is served from. A new script there may be a web shell, a back door that keeps working after the patch.[7, 15]
- A Hit Shows
- A script was created, changed or renamed in the web root, with the time and, in most tools, the program that wrote it.
- It Does Not Prove
- Deploys, plugin installs and updates write scripts there too. Start with any script that the web server or a PHP worker wrote itself, then check the rest against your own deploys and updates.
Defender XDRKQLSees It Directly
This table fills only on Linux servers onboarded to Defender for Endpoint. Change the two folders to your own web roots.
// Script files created, changed or renamed under the web roots, with the program that wrote each oneDeviceFileEvents
| where Timestamp > ago(30d)
| where ActionType in ("FileCreated", "FileModified", "FileRenamed")
| where FolderPath startswith "/var/www/" or FolderPath startswith "/srv/www/"
| where FileName endswith ".php" or FileName endswith ".phtml" or FileName endswith ".phar"
| extend Writer = tolower(InitiatingProcessFileName)
| extend ByWebProcess = Writer startswith "php" or Writer in ("apache2", "httpd", "nginx")
| project Timestamp, DeviceName, ActionType, FolderPath, FileName, Writer, ByWebProcess, InitiatingProcessCommandLine, InitiatingProcessAccountName, SHA1
| order by ByWebProcess desc, Timestamp descSentinelKQLSees It Directly
The Sentinel query loads from the article's query file, with what it needs switched on. Open the Query File
VelociraptorVQLSees It Directly
The Velociraptor query loads from the article's query file, with what it needs switched on. Open the Query File
SplunkSPLSees It Directly
The Splunk query loads from the article's query file, with what it needs switched on. Open the Query File
Check the Ways Back In
Attackers add their own ways back in, so they keep access after a web shell is found and removed. Look for new scheduled jobs in the cron tables, new services in the systemd units and new local accounts. Check each account's authorized_ file too, which holds the keys that let someone sign in over SSH from elsewhere.[7]
If You Find Something
Treat the server as compromised. Elastic Security Labs advises cutting it off from the network and keeping its web server and PHP logs. CISA's KEV entries also point US federal agencies to CISA's forensic triage requirements.[3, 7]
Attackers add their own ways back in, such as scheduled jobs and SSH keys. That is why standard practice is to rebuild the server from a clean source and patch it, instead of cleaning it where it stands.[7]
Standard practice is to change every secret the site could read, such as database passwords and API keys. Elastic Security Labs says an attacker who gets in almost always goes on to collect credentials and secrets files.[7]
Tools That Help
Rapid7 points to the Velociraptor artifact Generic.. Velociraptor is a free tool that collects evidence from many machines at once. This artifact lists the PHP installs, package versions and running PHP processes on each server, so you can find every server to patch.[5]
CISA's alert carries a Sigma detection rule, written in a shared format that many security tools can read. Unit 42 has published hunting queries for Palo Alto Networks' Cortex XDR and for its firewalls' threat logs.[4, 6]
Glossary
These are the terms this article uses, in plain words.
- CVE
- CVE stands for Common Vulnerabilities and Exposures. A CVE is a public id for one known flaw, such as CVE-2026-109618, so everyone names the same flaw the same way.
- CVSS
- The Common Vulnerability Scoring System, a score from 0 to 10 for how severe a flaw is. FIRST, which publishes it, rates 9.0 to 10.0 as Critical.[17]
- Remote Code Execution
- An attacker running their own commands on a machine from somewhere else, usually over the internet.
- Unauthenticated
- It means without signing in. The attacker needs no account and no password.
- Worker
- A running program that PHP keeps ready to handle web requests, one after another.
- Use-After-Free
- A bug where a program keeps using memory after it has handed that memory back, so it may read data that now belongs to something else. MITRE lists it as CWE-416.[16]
- Web Shell
- A small script an attacker leaves on a web server, so they can send it commands later through ordinary web requests. MITRE ATT&CK lists it as T1505.003.[15]
- KEV
- CISA's Known Exploited Vulnerabilities list of flaws with reliable evidence that attackers are using them. US federal agencies must fix each one by its due date.[3]
- mod_php
- A way of running PHP inside the Apache web server's own processes.
- PHP-FPM
- The FastCGI Process Manager, PHP's own service that runs pools of PHP workers apart from the web server.[18]
Sources
Every date, version, score and figure on this page comes from these public sources, checked on 1 November 2026. The numbers in the text point here.
- The PHP Foundation: today's PHP security release and how we're strengthening PHP security (21 October 2026) (opens in a new tab)
- PHP: security announcement for PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35 (21 October 2026) (opens in a new tab)
- CISA: Known Exploited Vulnerabilities entries for CVE-2026-109618 and CVE-2026-109619 (added 26 October 2026) (opens in a new tab)
- CISA: critical vulnerabilities in PHP require immediate patching (21 October 2026, revised 26 October) (opens in a new tab)
- Rapid7: CVE-2026-109618 and CVE-2026-109619, critical unauthenticated remote code execution in PHP (opens in a new tab)
- Unit 42: threat brief on PHP2Shell, CVE-2026-109618 and CVE-2026-109619 (updated 29 October 2026) (opens in a new tab)
- Elastic Security Labs: assessing Elastic detection coverage for PHP2Shell (21 October 2026) (opens in a new tab)
- BleepingComputer: Amazon says PHP2Shell exploitation began before the patches (22 October 2026) (opens in a new tab)
- iTWire: PHP2Shell, the 14-year-old bugs that pulled cyber.gov.au and government sites offline (23 October 2026) (opens in a new tab)
- W3Techs: usage statistics of server-side programming languages for websites (1 November 2026) (opens in a new tab)
- runZero: the PHP2Shell vulnerabilities, CVE-2026-109618 and CVE-2026-109619 (opens in a new tab)
- Microsoft Learn: Microsoft Defender for Endpoint on Linux (opens in a new tab)
- Microsoft Learn: DeviceProcessEvents table in the advanced hunting schema (opens in a new tab)
- Microsoft Learn: DeviceFileEvents table in the advanced hunting schema (opens in a new tab)
- MITRE ATT&CK: Server Software Component: Web Shell (T1505.003) (opens in a new tab)
- MITRE CWE-416: Use After Free (opens in a new tab)
- FIRST: CVSS v4.0 specification, the qualitative severity rating scale (opens in a new tab)
- PHP manual: FastCGI Process Manager (FPM) (opens in a new tab)
- NVD (NIST): CVE-2026-109618, with NIST's own CVSS v3.1 score and the PHP project's CVSS v4.0 score (opens in a new tab)
- NVD (NIST): CVE-2026-109619, with NIST's own CVSS v3.1 score and the PHP project's CVSS v4.0 score (opens in a new tab)
- CISA: BOD 23-02, mitigating the risk from internet-exposed management interfaces (13 June 2023) (opens in a new tab)
- OWASP Cheat Sheet Series: virtual patching (opens in a new tab)