---
title: "php2shell critical PHP flaws: who is affected, how to fix"
description: "PHP fixed two flaws allowing unauthenticated code execution on October 21, 2026. How to tell if a site runs PHP and is affected, risk by setup, update order and mitigation limits."
url: https://udon-dev.com/en/notes/php2shell-critical-rce/
lang: en
published: 2026-10-21
updated: 2026-10-25
topic: [security]
tags: ["security", "PHP", "脆弱性", "php2shell", "CVE-2026-109618", "CVE-2026-109619"]
---

# php2shell critical PHP flaws: who is affected, how to fix

- 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

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](https://www.php.net/) 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](https://www.php.net/archive/2026.php) 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](https://blog.flatt.tech/entry/php2shell) 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](https://piyolog.hatenadiary.jp/entry/2026/10/21/174516) 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](https://ubuntu.com/security/notices/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](https://www.ipa.go.jp/security/security-alert/2026/pre-alert20261021.html) 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.

（図: Image from the php-src security advisory showing the heading "RCE via OOM corruption," the PHP logo, the severity "Critical" and the publication date of October 21, 2026）
Source: [RCE via OOM corruption (php-src)](https://github.com/php/php-src/security/advisories/GHSA-w8hw-w9fx-j79w)

### 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](https://sansec.io/research/php2shell) 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](https://sansec.io/research/php2shell), 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](/en/notes/php2shell-after-patch/).

## What to do

1. **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
2. **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
3. **If you can't update right away, apply mitigations**: The settings below reduce the confirmed paths. They are a stopgap until you update
4. **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:

```sh
$ 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.
