PHP2Shell is the name for two critical flaws in the PHP engine itself, CVE-2026-109618 and CVE-2026-109619, disclosed on 21 October 2026. Either one can let an attacker with no login run code on a web server that uses PHP. Both are rated 9.2 on CVSS v4.0. Because the bugs are in PHP and not in any one application, WordPress, Drupal, Joomla, Magento and custom sites are all exposed when they run on an unpatched PHP build.
The short answer. Update to PHP 8.5.12, 8.4.27, 8.3.36 or 8.2.35 (or your distribution's patched package), then restart every PHP worker. PHP's maintainers say updating is the only complete fix. If you cannot patch today, turn off session.upload_progress.enabled, tighten request limits, and consider taking the site offline, as the UK's NCSC and CISA advise. Then check the server for signs of compromise, because exploitation attempts were seen before the patch existed.
How we checked. This guide is based on PHP's own security announcement and the two GitHub security advisories, the PHP Foundation's post, and reports from Amazon Threat Intelligence, the UK NCSC, Wiz, Akamai, watchTowr, Huntress, Tenable and CloudLinux, all read on 26 October 2026. We did not run any exploit or test the flaws ourselves, and this article contains no exploit code. The situation is still moving, so check the linked advisories for changes after this date.
PHP2Shell at a glance
| CVE-2026-109618 | CVE-2026-109619 | |
|---|---|---|
| PHP's title | RCE via OOM corruption | RCE via stale global state |
| Advisory | GHSA-w8hw-w9fx-j79w | GHSA-6wmf-4rv5-p3rp |
| CVSS v4.0 | 9.2 Critical | 9.2 Critical |
| Bug type | Out-of-memory handling leaves request data half built (CWE-416, CWE-824 and others) | Global state outlives the request memory it points to: a use-after-free (CWE-416) |
| Authentication needed | None | None |
| Confirmed RCE | Apache mod_php with default limits; PHP-FPM through application code paths | Apache mod_php; session path also validated on PHP-FPM |
| Fixed in | 8.5.12, 8.4.27, 8.3.36, 8.2.35 | 8.5.12, 8.4.27, 8.3.36, 8.2.35 |
Both advisories use the vector CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H: reachable over the network, no privileges or user interaction, high impact on confidentiality, integrity and availability, but with high attack complexity and some preconditions (GHSA-w8hw). That "high complexity" is why the score is 9.2 and not 10. A leaked score of 10.0 that circulated before disclosure was wrong, according to the PHP Foundation.
The name "PHP2Shell" comes from Wiz and refers to turning a PHP request into a shell on the server (Wikipedia).
Which PHP versions are affected
PHP lists every release before the fixed versions as vulnerable (PHP announcement). Wiz and Calif report that the flaws go back to PHP 5.4, released in 2012 (Wiz).
| PHP branch | Status | What to do |
|---|---|---|
| 8.5 | Fixed in 8.5.12 | Update |
| 8.4 | Fixed in 8.4.27 | Update |
| 8.3 | Fixed in 8.3.36 | Update |
| 8.2 | Fixed in 8.2.35 | Update |
| 8.6 (pre-release) | Fixed in 8.6.0 RC4 | Not for production; update test builds |
| 7.4, 8.0, 8.1 | End of life; no official release | Use a vendor or distribution backport, PHP's minimal source patches, or upgrade to 8.2+ |
| 7.3 and older, PHP 5 | End of life; no PHP.net fix | Upgrade, or use a commercial backport where one exists |
For the end-of-life branches 7.4, 8.0 and 8.1, PHP's security team published minimal source backports for people who build PHP themselves, but no official binaries (PHP announcement).
Distribution packages may keep the old version number. Linux distributions and long-term support vendors received the fix before the public release (PHP announcement). Many of them backport the patch into their existing package, so php -v can show something like 8.3.6 or 8.5.11 on a server that is already fixed. CloudLinux, for example, shipped the fix in alt-php85 8.5.11-5 and covers alt-php 5.2 through 8.5 (CloudLinux). Check the package changelog or your distribution's security tracker, not just the version string.
Who is most at risk
PHP says any installation that serves web requests is in scope, naming PHP-FPM, Apache with mod_php, php-cgi, FrankenPHP and LiteSpeed (PHP announcement). The risk is not equal across setups:
- Apache with mod_php: highest. PHP says it has a demonstrated exploit in which an unauthenticated request triggers the attack before any application code runs. Your own code cannot block it.
- PHP-FPM: high. The OOM advisory calls FPM susceptible from source analysis. The PHP Foundation reports RCE on FPM through application-level code paths, and the stale-state advisory says the session upload progress path was validated on FPM (PHP Foundation; GHSA-6wmf).
- FrankenPHP and LiteSpeed (LSAPI): likely susceptible but not validated, per the advisory.
- Command-line PHP (cron jobs, Composer, artisan commands) is not named in the advisories. It does not accept web requests, so the remote attack does not apply, but the same binary should still be updated.
Hidden PHP counts too. Many products bundle their own PHP: control panels, network appliances, monitoring tools and on-premises software. Tenable, for example, shipped an update to its Security Center to move its bundled PHP to 8.2.35 (Tenable). The NCSC tells organisations to watch for vendor updates for products that include PHP (NCSC).
How the two flaws work
You do not need these details to patch, but they explain why configuration changes only reduce the risk. The descriptions below are summarized from PHP's advisories and the Akamai and Wiz write-ups; we leave out exploitation steps.
CVE-2026-109618: out-of-memory corruption
When a request goes over memory_limit, PHP aborts it with longjmp(), jumping straight to request shutdown. Some request memory is reachable before it is fully initialized, so if an allocation fails at that moment, shutdown code can read or branch on invalid data. PHP says multipart parsing (the format used for file uploads) can trigger this out-of-memory condition while staying within PHP's normal limits (GHSA-w8hw). Akamai describes attackers first filling memory with forged structures and then forcing the out-of-memory error, so that shutdown follows an attacker-controlled function pointer (Akamai).
The fix replaces the longjmp() path with a "soft" out-of-memory error at the next safe point in the engine, plus an immediate hard exit at a higher threshold.
According to the PHP Foundation, a core developer first saw signs of this problem in 2024, while fixing an issue from an external audit funded by the Sovereign Tech Agency and carried out by Quarkslab. No concrete attack was found then, and the team could not agree on a fix. The Foundation calls the delay a "structural failure" in its decision process (PHP Foundation).
CVE-2026-109619: stale global state
A PHP worker keeps some global state (error, session, object and extension state) between requests. If a request ends in a fatal error, an out-of-memory error or a timeout, that state can still point to memory that has been freed. A later operation on the same worker that runs before normal request setup can then use the freed memory (GHSA-6wmf).
The advisory names two main ways this freed memory gets used:
- Session upload progress. This feature, on by default, writes upload progress into the session when a POST includes a
PHP_SESSION_UPLOAD_PROGRESSfield. It runs before your code, on any endpoint that accepts a multipart POST, even one that ignores uploads (Akamai). - INI warnings before request setup, such as invalid
php_valuelines in.htaccessunder mod_php. Hiding warnings witherror_reporting,display_errorsor@does not help.
On PHP 8.5, the fatal_error_backtraces feature gave a confirmed path to RCE against mod_php.
Wiz adds that the same family of bugs allows a memory disclosure: an attacker can read part of a worker's memory, which may hold passwords, tokens and API keys from other requests, even on sites that never start a session (Wiz). A patched server that was exposed before the update may therefore need its secrets rotated (see the checklist below).
How to check if you are vulnerable
The version that matters is the one your web server runs, which may differ from the command-line version. Check both.
Command-line PHP and packages (Debian, Ubuntu):
php -v
dpkg -l | grep -E '^ii +(libapache2-mod-)?php[0-9.]*(-fpm|-common|-cli)? '
RHEL, Rocky, AlmaLinux, Fedora:
php -v
rpm -qa | grep -E '^(php|alt-php)'
PHP-FPM binary (the name depends on your distribution, for example php-fpm8.3 on Debian and Ubuntu or php-fpm on RHEL):
php-fpm8.3 -v
php-fpm8.3 -i | grep -E 'session.upload_progress.enabled|memory_limit'
Apache mod_php runs inside Apache, so the only reliable check is a temporary phpinfo() page on that server. Put it behind authentication or an IP allowlist, read the version and settings, and delete it straight away.
If the version number looks old, look for the CVE IDs in the package changelog. A backported fix keeps the old version number:
apt changelog php8.3-common | grep -E 'CVE-2026-10961[89]'
rpm -q --changelog php-common | grep -E 'CVE-2026-10961[89]'
You can also look the CVEs up in your distribution's tracker, such as the Debian security tracker or Ubuntu CVE pages.
Containers: check the PHP version inside each image, not only on the host:
docker run --rm --entrypoint php your-image:tag -v
How to fix PHP2Shell
1. Patch
Install the fixed release or your vendor's patched package. Typical commands:
# Debian / Ubuntu
sudo apt update && sudo apt install --only-upgrade 'php*'
# RHEL family
sudo dnf upgrade 'php*'
# CloudLinux alt-php (CloudLinux 8, 9 and 10)
sudo dnf clean all && sudo dnf upgrade 'alt-php*'
The CloudLinux command comes from its own guidance, which also asks you to keep the php-els repository enabled (CloudLinux). On Windows, install the new build from windows.php.net, and remember that bundles such as XAMPP and Laragon ship their own copy of PHP.
Docker and Kubernetes: rebuild images with a fresh base image (for example docker build --pull), push them and redeploy. A running container does not pick up a patched host package. Pinned tags like php:8.3.30-fpm will not update themselves; move them to the fixed patch release.
Shared hosting: the host controls PHP. Check your provider's status page or ask support whether the fix is in place, and select a supported PHP version (8.2 or newer) in the control panel if you are on 8.1 or older.
2. Restart every PHP worker
The old code stays in memory until the process restarts. Restart PHP-FPM pools, Apache, LiteSpeed and any long-running PHP application servers:
sudo systemctl restart php8.3-fpm
sudo systemctl restart apache2 # or httpd on RHEL
watchTowr and PHP both stress the restart (watchTowr). After restarting, confirm the version again through the web server, not only on the command line.
3. Patch internet-facing servers first
The NCSC's order is: find PHP systems, starting with internet-facing ones; update them; apply PHP's temporary mitigations where you cannot update; and if you cannot do either quickly, consider taking the system offline (NCSC). CISA's 21 October alert also recommends taking PHP systems offline if they cannot be updated right away or still run PHP 8.1 or earlier, as summarized by Tenable.
Temporary mitigations if you cannot patch yet
PHP is clear that only an update is a complete solution. These steps, taken from its announcement and advisories, reduce exposure but do not make a server safe (PHP announcement).
For CVE-2026-109619 (stale state):
- Set
session.upload_progress.enabled=0inphp.ini, the FPM pool or the server configuration, then restart all workers. Do not rely onini_set()or an FPM.user.inifile, because those apply too late. PHP recommends leaving this off even after patching if you do not use the feature. - On PHP 8.5, set
fatal_error_backtraces=0and restart workers. This blocks only the confirmed backtrace path. - Remove invalid or deprecated per-directory settings (for example in
.htaccess) that produce warnings before a request starts. - Fix fatal errors and timeouts that an attacker can trigger. The advisory also suggests
pm.max_requests=1for PHP-FPM if you can afford the performance cost, so each worker handles only one request.
For CVE-2026-109618 (out of memory):
- Set
memory_limit=-1administratively (for example withphp_admin_valuein the FPM pool), so PHP's own limit cannot be hit, and add a container or cgroup memory limit that kills only the affected worker. Do not useRLIMIT_ASorRLIMIT_DATA. Without an outer limit, an unlimitedmemory_limitinvites memory exhaustion, so treat this as a short-term measure. - Keep
post_max_sizesmall: PHP suggests8Mif you do not accept uploads or32Mif you do, withupload_max_filesizebelow it. - At the web server or proxy, cap request size, field count, multipart parts, headers and nesting depth. If the site does not need uploads, block multipart requests entirely.
A minimal php.ini fragment for an FPM pool that does not take uploads might look like this:
; /etc/php/8.3/fpm/pool.d/www.conf (example path)
php_admin_value[session.upload_progress.enabled] = 0
php_admin_value[post_max_size] = 8M
php_admin_value[upload_max_filesize] = 2M
WAF rules from providers such as Cloudflare, Fastly, Vercel, Google and AWS can block known exploit patterns while you patch (Wiz; AWS). They are a stopgap; variants can get past signature rules.
One trap that comes up often in community discussion: the command-line and FPM versions of PHP usually read different php.ini files, so a setting can look off with php -i while still on in FPM. Check the effective value through php-fpm -i or a protected phpinfo() page (Hacker News discussion).
Is PHP2Shell being exploited?
Sources disagree on how much, so here is what each one says:
- Amazon Threat Intelligence saw an exploitation attempt against its MadPot honeypots on 17 October 2026, four days before disclosure, and several more from apparently different actors on 21 October, before the patch. It is not known whether those attempts would have worked against real systems. Amazon later described the flaws as broadly exploited in the wild (AWS).
- watchTowr reports exploitation attempts through its honeypot network since 21 October (watchTowr).
- Cloudflare reported "early attacks emerging," as quoted by Tenable.
- The PHP Foundation said the proof-of-concept code it inspected around release time was not functional (PHP Foundation). Other researchers, including Wiz and Calif, have since published working attack demonstrations against WordPress, Drupal and Joomla.
- CISA said on 21 October that it had not yet observed exploitation, and the flaws were not in its Known Exploited Vulnerabilities catalog as of 23 October, per Tenable. Check the KEV catalog for the current status.
The practical reading: attempts are real and started before the patch, so assume any exposed, unpatched server may have been targeted.
How to check for compromise
Patching closes the hole but does not remove anything an attacker left behind. The NCSC specifically advises checking for backdoors (NCSC). Start your review from 17 October 2026, the earliest known attempt, not the disclosure date, as Amazon recommends.
In web server logs:
- POST requests containing
PHP_SESSION_UPLOAD_PROGRESS, especially to pages that do not take uploads (AWS). - Unusual multipart requests followed by memory-limit errors, bursts of HTTP 500 responses, oversized or malformed
PHPSESSIDcookies in responses, and unexplained worker crashes or restarts (Wiz).
A quick first search of Apache or Nginx logs:
grep -l 'PHP_SESSION_UPLOAD_PROGRESS' /var/log/apache2/*access* /var/log/nginx/*access* 2>/dev/null
grep -E 'Allowed memory size|zend_mm_heap corrupted|SIGSEGV' /var/log/php*fpm*.log /var/log/apache2/error*.log 2>/dev/null
Access logs usually record only the URL, not the POST body, so an empty result is not proof that nothing happened.
On the server (from Huntress):
- PHP or web server processes (
php-fpm,php-cgi,httpd,apache2) starting shells (sh,bash,cmd.exe,powershell.exe), interpreters (python,perl) or download tools (curl,wget,nc,certutil.exe). - Reconnaissance commands such as
whoami,idoruname -arun by the web user, and command lines containing/dev/tcp/,mkfifoorfsockopen, which suggest reverse shells. - New or changed PHP files in the web root and upload folders, new cron jobs or scheduled tasks, and new user accounts.
To list PHP files changed since the earliest known attempt:
find /var/www -name '*.php' -newermt '2026-10-17' -type f
Legitimate updates will show up too, so compare against your deployments or a known-good copy.
If you find signs of compromise, isolate the host, preserve logs, rebuild from a clean source rather than cleaning in place, and rotate secrets the PHP process could read: database passwords, API keys, session secrets and cloud credentials. Because of the memory disclosure path, rotating secrets on any server that was exposed and unpatched is a reasonable precaution even without other signs.
Timeline
| Date (2026, UTC) | Event |
|---|---|
| 11 August | Calif reports the full impact to PHP (the OOM issue had first been noticed in 2024) |
| 17 October | Earliest exploitation attempt seen by Amazon's honeypots |
| 20 October | CVE IDs leak; PHP announces an emergency release for 21 October |
| 21 October, 07:41 | Chainguard publishes fixed images about six hours before the coordinated release |
| 21 October, 14:00 | PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35 released; advisories published |
| 21 October | NCSC and CISA alerts; Wiz, Calif and others publish technical details |
| 23 October | PHP publishes an informational note on a related session issue (CVE-2026-115560) |
Sources: PHP Foundation, PHP archive, AWS, NCSC.
A follow-up issue to watch: CVE-2026-115560
On 23 October PHP published an informational note about a further, less likely code-execution path in session upload progress. It needs an unusual setup: session.serialize_handler set to php_binary or php_serialize in configuration and then switched to php with ini_set() before session_start(), while upload progress is enabled. Until the next regular release, PHP suggests keeping session.upload_progress.enabled=0. Applications that never change the serialize handler at runtime can keep the feature on. A full advisory for CVE-2026-115560 is due with the next release (PHP archive).
How PHP2Shell compares with earlier PHP flaws
PHP2Shell is unusual because it sits in the core engine and needs no particular application or OS. The last widely exploited PHP flaw, CVE-2024-4577, was narrower: an argument-injection bug in PHP-CGI on Windows with certain Asian-language code pages, where a soft-hyphen character was mapped to a normal hyphen and slipped past an older fix for CVE-2012-1823. It was fixed in PHP 8.3.8, 8.2.20 and 8.1.29 (GHSA-3qgc-jrrr-25jv). Most PHP security problems are still in applications and plugins, not PHP itself, which is why PHP2Shell drew so much attention.
The common lesson from both: end-of-life PHP versions stop getting fixes, and when a core flaw arrives, sites on old branches have the hardest path. If you are on 8.1 or older, plan the upgrade to 8.2 or newer now, even if a backport covers you this time.
PHP2Shell response checklist
- Inventory every PHP install: servers, containers, control panels, appliances and vendor software.
- Check the web server's PHP version and the package changelog for the two CVE IDs.
- Patch to 8.5.12, 8.4.27, 8.3.36 or 8.2.35, or a vendor backport; rebuild container images.
- Restart every PHP-FPM pool, Apache and LiteSpeed process, then confirm the version through the web server.
- Mitigate what you cannot patch: disable session upload progress, cap request sizes, add WAF rules, or take it offline.
- Hunt for compromise from 17 October onward: logs, child processes, new files, cron jobs and accounts.
- Rotate secrets on servers that were exposed while unpatched.
- Upgrade off end-of-life branches and subscribe to PHP's security announcements.
FAQ
Does PHP2Shell affect WordPress sites?
Yes, if the server's PHP is unpatched. The flaw is in PHP, not WordPress, so updating WordPress or its plugins does not fix it. Wiz demonstrated unauthenticated code execution against WordPress, Drupal and Joomla (Wiz). On managed or shared hosting, your host has to update PHP; check with them.
Is disabling session.upload_progress enough?
No. It blocks one known path for CVE-2026-109619, but it does nothing for CVE-2026-109618, and PHP says no configuration change fully mitigates either flaw (GHSA-6wmf). Use it as a stopgap and keep it off after patching if you do not need upload progress.
My server shows an older PHP version. Am I vulnerable?
Not necessarily. Distribution packages often backport the fix without changing the upstream version number. Check the package changelog or your distribution's security tracker for CVE-2026-109618 and CVE-2026-109619.
Do I need to restart after updating?
Yes. Running PHP-FPM pools and Apache processes keep the old code in memory until they restart.
Is PHP 7.4 or 8.1 still safe to run?
They are end of life, so PHP.net does not ship fixed releases for them. Minimal source patches and some vendor backports exist, but the long-term fix is upgrading to a supported branch (8.2 or newer).
Stay up to date
The fastest way to hear about the next PHP security release is the php.announce mailing list or the PHP-src security advisories page. You can follow both, along with security research blogs, in a feed reader; our guide on following technical blogs with RSS shows how. For more engineering and security blogs, browse the Programming and Technology section of the directory.
This article is general information for administrators and developers, not a substitute for your vendor's guidance or professional incident response. Last checked against the sources below on 26 October 2026.
References
Primary sources
- PHP Group. Security release announcement for PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35, 21 October 2026, and related October 2026 news entries. php.net/archive/2026.php
- PHP security team. "RCE via OOM corruption," GHSA-w8hw-w9fx-j79w (CVE-2026-109618), 21 October 2026. GitHub
- PHP security team. "RCE via stale global state," GHSA-6wmf-4rv5-p3rp (CVE-2026-109619), 21 October 2026. GitHub
- The PHP Foundation. "Today's PHP security release and how we're strengthening PHP security," 21 October 2026. thephp.foundation
- UK National Cyber Security Centre. "Critical security issue affecting PHP," 21 October 2026, updated 23 October. ncsc.gov.uk
- PHP security team. "PHP RCE: A Bypass of CVE-2012-1823, Argument Injection in PHP-CGI," GHSA-3qgc-jrrr-25jv (CVE-2024-4577). GitHub
Independent analysis
- CJ Moses, Amazon Threat Intelligence. "Amazon Threat Intelligence identifies PHP2Shell exploitation prior to public disclosure in MadPot," 21 October 2026. AWS Security Blog
- Wiz Research. PHP2Shell technical write-up, 21 October 2026. wiz.io
- Akamai Security Intelligence Group. "Understanding PHP2Shell: Everything You Need to Know," 22 October 2026. akamai.com
- watchTowr. "Frequently Asked Questions About PHP Remote Code Execution (PHP2Shell)," 20 October 2026, updated 23 October. watchtowr.com
- Huntress. PHP2Shell detection guidance, 21 October 2026. huntress.com
- Tenable. "php2shell (CVE-2026-109618, CVE-2026-109619): Critical PHP RCE FAQ," 21 October 2026, updated 23 October. tenable.com
- CloudLinux. alt-php update notes for CVE-2026-109618 and CVE-2026-109619, updated 23 October 2026. blog.cloudlinux.com
Background and community
- Wikipedia. "PHP2Shell," accessed 26 October 2026. en.wikipedia.org
- Hacker News discussion of the PHP security release, October 2026 (individual practitioners' views). news.ycombinator.com