The code nobody touched for years just became everyone's problem. A bug hiding in PHP since 2012 lets strangers run code on web servers, and the NSA and India's CERT-In have both raised the alarm. Here's how PHP2Shell (CVE-2026-109618 and CVE-2026-109619) works, how it was found, and exactly what to do about it.
On 21 October 2026, PHP shipped an emergency release for two critical bugs in the PHP engine itself: CVE-2026-109618 and CVE-2026-109619, nicknamed PHP2Shell. Both let an attacker run code on a web server without logging in [1][2].
Governments moved fast. The NSA told organizations that can't update right away to take their PHP systems offline [3]. The same day, India's national cybersecurity agency, CERT-In, issued a critical-severity advisory (CIVN-2026-0510) warning that vulnerable PHP servers could be exposed to remote code execution [10][11]. CISA in the US issued its own alert [6].
The unsettling part is where the bugs came from: code that has sat in PHP since 2012, and that attackers started probing before a patch existed. This post explains what the two bugs are, how they work, how they were found, and what to do about them. If you run PHP anywhere, including inside WordPress, Drupal, Magento or an internal tool, it applies to you.
The Two Bugs at a Glance
| CVE-2026-109618 | CVE-2026-109619 | |
|---|---|---|
| Name in the advisory | RCE via OOM corruption | RCE via stale global state |
| Bug type | Memory corruption when PHP runs out of memory | Use-after-free across two requests |
| Severity | CVSS v4.0 9.2, critical | CVSS v4.0 9.2, critical |
| Login needed? | No | No |
| Confirmed exploit | Apache mod_php | mod_php and PHP-FPM |
| Advisory | GHSA-w8hw-w9fx-j79w | GHSA-6wmf-4rv5-p3rp |
In both cases, a successful attack runs code as the web server's PHP user. From there an attacker can read files, steal database passwords and keys from config files, or plant a backdoor [1][2].
How the Bugs Work
CVE-2026-109618: running out of memory at the wrong moment
When PHP runs out of memory, it doesn't return an error step by step. It jumps straight out of whatever it was doing, using a C function called longjmp(). If that happens while a request is still being set up, some of the request's data is left half-built. Later, when PHP cleans up the request, it treats that half-built data as valid, and memory gets corrupted [1].
An attacker can cause this on purpose. Weaknesses in how PHP parses multipart form uploads let a crafted request use up memory while still looking like it's within the configured limits. On Apache with mod_php, this happens before any application code runs, so the app itself doesn't need to have a bug [1][4].
CVE-2026-109619: one request's leftovers, used by the next
A PHP worker handles many requests in a row, and it keeps some global state between them: error, session and extension data. Normally that state is reset at the end of each request. But a fatal error, such as running out of memory or hitting the execution time limit, can skip that reset. The worker is left holding a pointer to memory that's already been freed [2].
If the next request on the same worker touches that state before it's reset, PHP uses freed memory. The advisory confirms two ways to reach it. One is session upload progress, a feature that's on by default and works even if the app never calls session_start(). The other is PHP 8.5's new fatal error backtraces setting, also on by default. Besides running code, this bug can leak memory from other users' requests, including passwords and tokens [2].
How It Was Found
Both bugs were found in August 2026 by researchers auditing PHP's C source with the help of AI models. Researcher Ryan Austin at Calif found one during an audit run under OpenAI's "Patch the Planet" project. Wiz found the same flaws independently, using AI models alongside its own tooling [5]. The PHP advisories credit reporters from both efforts and others [1][2].
The weakness wasn't entirely new. In 2024 a PHP core developer spotted the out-of-memory problem behind CVE-2026-109618 during an audit, but the team couldn't agree on a fix, and a working exploit was thought unlikely, so it wasn't prioritised [5]. The affected code dates back to PHP 5.4, released in 2012.
Timeline
The release was meant to be a normal coordinated disclosure, but it didn't stay quiet. Amazon's honeypots logged an exploit attempt on 17 October, four days early. On 20 October news leaked on Hacker News, watchTowr posted about it, and a proof-of-concept video was published by mistake, so PHP announced the release a day ahead. The fixes and the two GitHub advisories went out on 21 October, the same day as alerts from CISA, the NSA, India's CERT-In and others [5][6][10].
Some organizations didn't wait. Government portals in the Netherlands, Finland and France, many Wikimedia services and the Internet Archive went offline for a time as a precaution. Wiz compared the bug to Heartbleed, the 2014 OpenSSL flaw [5].
Am I Affected?
- Versions: everything from PHP 5.4 up to, but not including, 8.2.35, 8.3.36, 8.4.27 and 8.5.12 [1][2].
- Server setups: any PHP that serves web requests: Apache mod_php (highest risk), PHP-FPM, php-cgi, FrankenPHP and LiteSpeed [4].
- Old versions: PHP 8.1 and older are end of life. The PHP team released source patches for 7.4, 8.0 and 8.1, but no official builds. Older versions get nothing [5].
- Hidden PHP: PHP is often bundled inside other products, such as control panels, appliances and vendor software. Cisco, for example, published its own advisory for affected products [6][7].
To check a server, look at the version and the two settings that matter most:
php -v
php -i | grep -E 'session.upload_progress.enabled|fatal_error_backtraces|memory_limit'
Run this with the same PHP the web server uses. The command-line PHP can be a different version from PHP-FPM or mod_php, so also check your web server's phpinfo() page or package list.
What to Do Now
For security teams, this goes beyond applying an update. The work falls into four steps: patch, mitigate, contain and investigate. Start by finding every PHP install, internet-facing ones first [6].
1. Patch
Upgrade to a fixed release: 8.5.12, 8.4.27, 8.3.36 or 8.2.35, or your Linux distribution's patched package. Then restart every PHP worker: PHP-FPM, Apache and any long-running PHP processes. Until they restart, the old code is still running [1][2].
2. Mitigate, if you can't patch today
The PHP advisories list temporary settings. Set them in php.ini, the PHP-FPM pool or the web server config. Setting them with ini_set() or .user.ini is too late to help [1][2][4].
; CVE-2026-109619: closes the confirmed session path.
; Worth keeping off after patching if you don't use upload progress bars.
session.upload_progress.enabled = 0
; CVE-2026-109619, PHP 8.5 only: closes the confirmed backtrace path.
fatal_error_backtraces = 0
; CVE-2026-109618: avoids the out-of-memory jump. Not a complete fix,
; so pair it with tight request limits below and at your proxy.
memory_limit = -1
post_max_size = 8M
upload_max_filesize = 2M
- Limit requests before they reach PHP. At nginx, Apache or your load balancer, cap request size, the number of form fields and multipart parts, and headers per part. If your app doesn't take file uploads or multipart forms, block them entirely [1].
- Put a web application firewall in front if you have one [6].
-
Don't rely on
RLIMIT_ASorRLIMIT_DATA. These operating system memory limits can trigger the very bug you're trying to avoid [1]. -
Hiding errors doesn't help. Turning off
display_errorsor using@doesn't stop the stale state from being used [4].
These settings only close the paths researchers have confirmed so far. Both advisories say updating is the only complete fix [1][2].
3. Contain
If an internet-facing system can't be patched yet, or runs PHP 8.1 or older, take it offline until it's patched or upgraded. This is what the NSA and CISA both advise [3][6]. Several governments, Wikimedia and the Internet Archive did exactly this on 21 October [5].
4. Investigate
Exploit attempts started before the patch, so a patched server may already have been hit. Look for:
- PHP worker processes starting a shell (
sh,bash) or tools likecurlandwget[6]. - Signs of persistence: new or changed
.phpfiles in web directories (especially upload folders), new cron jobs or new user accounts. - Unexpected outbound connections from web servers.
- Bursts of large or unusual multipart POST requests in your access logs.
Clean logs don't prove a server is safe [2]. If you find signs of compromise, treat it as an incident: rotate the database passwords and API keys stored on that server, not just the PHP version.
The Bigger Lesson
Legacy code isn't harmless just because it's familiar. The code behind PHP2Shell had run on millions of servers for 14 years, and it was trusted because nothing had gone wrong yet.
Neither bug was in anyone's PHP code. Both were memory-safety bugs in the PHP engine, which is written in C: memory used after it was freed, and data used before it was fully set up. These are the same classes of bug the NSA and CISA have pointed to for years when they urge a move to memory-safe languages for new code [8][9].
Two other points stand out. AI-assisted audits found bugs that had sat in widely used code for over a decade, and attackers have the same tools. And PHP runs a large share of the web, yet the PHP Foundation has only 13 employees and relies on donations [5]. If your business depends on PHP, supporting the foundation is part of keeping it safe.
For now, the steps are simple: find every PHP server, update it, restart it, and check it wasn't hit first.
References
Advisories
- PHP. RCE via OOM corruption (CVE-2026-109618, GHSA-w8hw-w9fx-j79w). https://github.com/php/php-src/security/advisories/GHSA-w8hw-w9fx-j79w
- PHP. RCE via stale global state (CVE-2026-109619, GHSA-6wmf-4rv5-p3rp). https://github.com/php/php-src/security/advisories/GHSA-6wmf-4rv5-p3rp
- NSA Cybersecurity. Post on PHP vulnerabilities, 21 October 2026. https://x.com/NSACyber/status/2112903220209098897
Analysis and background
- Rapid7. CVE-2026-109618 and CVE-2026-109619: Critical Unauthenticated Remote Code Execution in PHP. https://www.rapid7.com/blog/post/etr-cve-2026-109618-and-cve-2026-109619-critical-unauthenticated-remote-code-execution-in-php/
- Wikipedia. PHP2Shell. https://en.wikipedia.org/wiki/PHP2Shell
- CISA. Critical Vulnerabilities in PHP Require Immediate Patching, 21 October 2026. https://www.cisa.gov/news-events/alerts/2026/10/21/critical-vulnerabilities-php-require-immediate-patching
- Cisco. Vulnerabilities in PHP Affecting Cisco Products: October 2026. https://sec.cloudapps.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-php-october26-Jj384Daq
- NSA. Software Memory Safety (Cybersecurity Information Sheet). https://media.defense.gov/2022/Nov/10/2003112742/-1/-1/0/CSI_SOFTWARE_MEMORY_SAFETY.PDF
- CISA. The Case for Memory Safe Roadmaps. https://www.cisa.gov/resources-tools/resources/case-memory-safe-roadmaps
- CERT-In. Vulnerability Note CIVN-2026-0510: PHP2Shell vulnerabilities in PHP, 21 October 2026. https://www.cert-in.org.in/s2cMainServlet?VLCODE=CIVN-2026-0510&pageid=PUBVLNOTES01
- NewsBytes. US NSA and India's CERT-In flag 'PHP2Shell' web risk. https://www.newsbytesapp.com/news/science/us-nsa-and-indias-cert-in-flag-php2shell-web-risk/tldr
CobuildX helps teams modernise legacy systems with MigrateX.
Originally published on the CobuildX blog.


Top comments (0)