php2shell critical PHP flaws: who is affected, how to fix
TL;DR
- Any PHP running on a web server is affected, whatever the setup. Update right away to 8.5.12, 8.4.27, 8.3.36 or 8.2.35 (for distribution PHP, the vendor's fixed packages)
- Both flaws (CVE-2026-109618 and CVE-2026-109619) can allow arbitrary code execution from unauthenticated requests alone. Both are rated 9.2 under CVSS v4.0
- Apache mod_php is the most exposed: an attack works in a single request, before any application code runs. Input validation in the application can't stop it
- After the fixed versions came out, an exploit tool was published, and unauthenticated code execution has been confirmed on 11 applications, including WordPress and Laravel
- Configuration mitigations only close some paths, and PHP says updating is the only complete fix. PHP 8.1 and earlier get no official update
Contents (15)
- What happened
- Is your server affected?
- Any PHP serving the web is affected
- How to tell whether a site or server runs PHP
- Fixed version numbers, and checking distribution PHP
- What the flaws are
- Flaw 1: processing stops midway on out-of-memory (CVE-2026-109618)
- Flaw 2: state from a previous request is left behind (CVE-2026-109619)
- Why it’s urgent
- The attack lands before application defenses run
- The two conditions behind the 9.2 score, and their limits
- An exploit tool is public
- What to do
- Mitigations when you can’t update right away
- Prepare in case you’ve been breached
On October 21, the PHP development team released fixed versions for two flaws that can allow arbitrary code execution without authentication. The pair is also called “php2shell.” Based on the official advisory published alongside the fixed versions, this post walks through whether your server is affected and where to start.
What happened
About a day passed between the pre-announcement and the release. In that window, details leaked and reports of attacks appeared. All times below are Japan Standard Time (JST, UTC+9).
| When | What |
|---|---|
| October 20 | PHP announces fixed versions for two critical flaws for the next day, without details |
| October 20–21 | Details circulate earlier than planned. A video demonstrating an attack is posted, then removed |
| October 21, 14:00 | GMO Flatt Security adds a note that code claimed to be exploitable has started circulating |
| October 21, 15:00–22:59 | Services and sites in Japan announce shutdowns and emergency maintenance one after another |
| October 21, 16:43 (07:43 UTC) | Cloudflare reports early attacks on PHP sites (according to Sansec) |
| Night of October 21 (scheduled for 23:00) | Fixed versions and the official advisory are published |
| After the release | A technical write-up and an exploit tool are published |
In Japan, companies including BASE (an online store builder) and Cygames (a game developer) suspended services before the fix. By the count of piyolog, a Japanese security incident blog, 54 organizations had announced shutdowns or emergency maintenance through the 22:00–22:59 window on the 21st (including announcements that did not name PHP as the reason).
Is your server affected?
Any PHP serving the web is affected
The official advisory says the flaws affect “every PHP installation that handles web requests.” Servers running PHP applications such as WordPress, Drupal, Magento or Laravel are affected, whatever the application.
According to the advisory, how far attacks have been confirmed differs by setup:
| Setup | What has been confirmed |
|---|---|
| Apache mod_php | Attacks confirmed for both flaws. PHP calls it the most exposed |
| PHP-FPM | Attack confirmed for the second flaw (when the application has code that meets the conditions). No full attack shown yet for the first |
| FrankenPHP | First flaw likely affects it, based on source analysis (unverified). For the second, no code path used under the default settings has been found (that doesn’t mean it’s unaffected) |
| LiteSpeed (LSAPI) | First flaw likely affects it (unverified). Second is a candidate depending on conditions |
“Unverified” and “not found” do not mean safe. Every setup needs the update.
How to tell whether a site or server runs PHP
From the outside, the response headers are a clue. According to the PHP manual, when the expose_php setting is on (the default), PHP adds an X-Powered-By header with its version to responses. In the test environment (PHP 8.3.6), PHP’s built-in web server also sent X-Powered-By: PHP/8.3.6 under the default settings, and no such header with the setting turned off. Because this setting can be turned off in php.ini, a site without the header may still run PHP.
If you can log in to the server, php -v shows the version. That is the version of the command-line PHP. For PHP running as FPM or an Apache module, also check the package list (on Ubuntu, dpkg -l | grep php).
Fixed version numbers, and checking distribution PHP
The four official fixed versions are below. Both fixes ship in the same releases.
| Branch | Fixed version |
|---|---|
| PHP 8.5 | 8.5.12 |
| PHP 8.4 | 8.4.27 |
| PHP 8.3 | 8.3.36 |
| PHP 8.2 | 8.2.35 |
Support for PHP 8.2 ends on December 31, 2026, with no security fixes after that, so PHP asks users to plan a move to a supported version.
For PHP from a Linux distribution, comparing against these numbers won’t tell you anything. Distributions often backport fixes without changing the version number. On Ubuntu 24.04, for example, the PHP package version is 8.3.6-0ubuntu0.24.04.12. Vendors received the fixes in advance, and Ubuntu has shipped fixed packages in USN-8948-1. Check each vendor’s security notices.
If any of these three apply, installing the versions above is not enough:
- PHP 8.1 and earlier: There is no update from the PHP development team. Given the severity, the team prepared minimal fixes in source form for 7.4, 8.0 and 8.1 this time, but PHP asks users to contact a long-term support vendor or upgrade to a supported version.
- Packages from
rpms.remirepo.net: This repository is run by a volunteer, and according to PHP, no update will come out on this day. PHP recommends switching to distribution packages or building from source - PHP inside products and appliances: IPA also calls attention to PHP used inside products and network equipment. Users may not be able to see the PHP inside, so check the product manual or the vendor’s security notices
What the flaws are
Both let an attacker run arbitrary code with the web server worker’s privileges just by sending unauthenticated requests. Both are rated 9.2 (Critical) under CVSS v4.0.

Flaw 1: processing stops midway on out-of-memory (CVE-2026-109618)
When PHP runs out of memory, it aborts processing on the spot. According to PHP, the request’s internal data can be left half-built at that moment, and cleanup code then treats it as valid data. Triggers for the out-of-memory condition include parsing multipart bodies (the format used for file uploads and similar). PHP confirmed code execution over HTTP on mod_php with the default input and memory limits.
The fixed versions now advance processing to a safe point before stopping when memory runs out.
Flaw 2: state from a previous request is left behind (CVE-2026-109619)
A PHP worker handles multiple requests in turn within one process. According to PHP, the internal state of a request that ended in a fatal error (including out-of-memory) can remain even after its memory is freed. The second flaw is that the next request handled by the same worker can use that state before it is initialized.
One confirmed path uses the session upload progress feature (session.upload_progress). The feature is on by default and is used even if the application never calls session_start(), so the attack works under the default settings. On PHP 8.5, a path through fatal error backtraces (fatal_error_backtraces) has also been confirmed.
Why it’s urgent
The attack lands before application defenses run
On mod_php, which PHP calls the most exposed, an attack has been demonstrated to start from a single unauthenticated request before a single line of application code runs. The flaw is in PHP itself, so input validation in applications such as WordPress or Laravel won’t stop the attack, and neither will application code that has no bugs. Sansec also urges users to update without waiting for its own rules, saying the attack arrives before its protection product does.
The two conditions behind the 9.2 score, and their limits
The score isn’t a perfect 10.0 because two factors lower it: high attack complexity (AC:H) and attack prerequisites (AT:P). The vector for both flaws is AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H. For the second flaw, for example, the request that leaves state behind and the request that uses it must hit the same worker.
However, PHP says the number of workers and the volume of traffic only increase the number of attempts an attacker gets. They don’t remove the conditions. Adding servers or workers does not make you safe. Some reports said “CVSS 10.0,” but PHP has rated the flaws 9.2 from the start.
An exploit tool is public
IPA warned that attackers could launch attacks within a very short time and asked organizations to be ready to apply the fixed versions immediately.
Before the release, views on real-world exploitation differed. As of the 20th and 21st, IPA, watchTowr and Huntress said they had not confirmed any, while Tenable reported that Cloudflare’s CTO had said the company was seeing early attacks.
After the release, Calif, said to be the author of the exploit tool, confirmed unauthenticated code execution on 11 applications. According to Sansec, these include WordPress 7.1.2, Drupal 11.4.3, Laravel 13.11 and Magento 2.4.9. With a technical write-up and exploit tool public, Sansec expects large-scale exploitation. I covered post-release exploitation reports and how to check after updating in a follow-up.
What to do
- Inventory what uses PHP: IPA asks organizations to take stock of which programs they develop and run use PHP. That covers your own servers and also products and appliances that use PHP internally
- Update to a fixed version: Use a version from the table above or your distribution’s fixed package. Restart PHP-FPM or Apache and confirm that every worker is running the new version
- If you can’t update right away, apply mitigations: The settings below reduce the confirmed paths. They are a stopgap until you update
- Prepare for a breach: Preserve logs and prepare to limit damage if you have been compromised
Mitigations when you can’t update right away
The mitigations in the official advisory are split by flaw. PHP states clearly that each one only reduces specific attack paths and does not make you safe.
Mitigations for the first flaw (out-of-memory):
| Setting | What to watch for |
|---|---|
memory_limit=-1 | Set it where the application can’t override it (the FPM pool or php_admin_value in the Apache config), and check that no other setting puts it back to a finite value. Even so, the original allocation failure can still reach the vulnerable code |
Lower post_max_size | 8M for applications that don’t need file uploads, 32M for those that do. Set upload_max_filesize lower than that |
| Set limits in the web server or proxy | Body size, number of input fields, number of multipart parts, number of headers and nesting depth. Cover requests without a usable Content-Length too |
Reject multipart/form-data | Only for applications that don’t use multipart, such as for file uploads. According to Sansec, every known attack trigger arrives in this format |
| Set memory limits with containers or cgroups | Don’t use RLIMIT_AS or RLIMIT_DATA instead, because they can cause the vulnerable allocation failure |
memory_limit=-1 also lets a single request use up all of the server’s memory. Sansec writes that, as a short-term measure, it should be used while monitoring memory usage.
Mitigations for the second flaw (leftover state):
| Setting | What to watch for |
|---|---|
session.upload_progress.enabled=0 | Set it somewhere that takes effect before request parsing, such as php.ini, the FPM pool or the server config, and restart all workers. It has no effect via ini_set() or FPM’s .user.ini. It closes the confirmed path but doesn’t stop other variants |
fatal_error_backtraces=0 | PHP 8.5 only. Restart all workers |
FPM pm.max_requests=1 | If performance allows. Replaces the worker after every request (described in GHSA-6wmf-4rv5-p3rp) |
| Remove settings that emit warnings before initialization | Invalid or deprecated settings among those applied per request. Hiding warnings with error_reporting, display_errors or @ doesn’t help |
| Fix fatal errors an attacker can trigger | Including execution timeouts and failures in callbacks, upload or import handling, and cleanup |
You can check on your own PHP whether session.upload_progress.enabled is on by default. In the environment I tested (Ubuntu 24.04.5 LTS, PHP 8.3.6 CLI), the built-in defaults without reading php.ini (-n) were:
$ php -n -r 'foreach (["session.upload_progress.enabled","memory_limit","post_max_size","upload_max_filesize"] as $k) printf("%s = %s\n", $k, var_export(ini_get($k), true));'
session.upload_progress.enabled = '1'
memory_limit = '128M'
post_max_size = '8M'
upload_max_filesize = '2M'
session.upload_progress.enabled is '1' (on), matching the advisory’s “on by default.” CLI values aren’t necessarily the same as those of PHP running under a web server. To see the settings used on the web, read the FPM or Apache config files, or output phpinfo() somewhere only administrators can open.
Prepare in case you’ve been breached
Even on servers you’ve already updated, it seems wise to preserve the logs of traffic that arrived between the pre-announcement and the update before they’re rotated away.
Separately from applying the patch, GMO Flatt Security lists preparations to reduce the damage if code is run on your server. There are three: keep only the data you need on the server, narrow the permissions of cloud IAM roles and service accounts, and review whether logs are recorded and kept in a tamper-resistant form so you can investigate an intrusion later.
Verification
- Last verified
- Environment
- Ubuntu 24.04.5 LTS
- PHP 8.3.6 CLI (package 8.3.6-0ubuntu0.24.04.12)
Changelog
- Reflected Ubuntu's release of fixed packages (USN-8948-1) and added a link to the follow-up covering developments after the fixed versions came out
- Added how to tell whether a server or site runs PHP (`php -v`, the package list, the `X-Powered-By` header), checked against the PHP manual and a local test
Spotted an error or something out of date? Let me know on X.


