---
title: "PHP2Shell: Unauthenticated RCE in PHP (CVE-2026-109618, CVE-2026-109619)"
description: "Two critical PHP engine flaws allow unauthenticated remote code execution on unpatched web servers, mod_php first. What is affected and what to do today."
url: https://panop.io/threat-intelligence/php2shell-cve-2026-109618-cve-2026-109619/
---

Vulnerability advisory Severity: Critical 21 October 2026 [Panop Research](https://panop.io/company)

# PHP2Shell: Unauthenticated RCE in PHP (CVE-2026-109618, CVE-2026-109619)

Two memory-safety flaws in the PHP engine let an unauthenticated HTTP request execute code on unpatched servers. On Apache with mod\_php, the PHP project demonstrated it before any application code runs. Fixed releases shipped on 21 October 2026: patch, restart every worker, and treat the configuration workarounds as a bridge, not a fix.

CVEs

[CVE-2026-109618](https://github.com/php/php-src/security/advisories/GHSA-w8hw-w9fx-j79w)
[CVE-2026-109619](https://github.com/php/php-src/security/advisories/GHSA-6wmf-4rv5-p3rp)

CVSS v4.0

9.2

Affected

PHP serving web requests, any SAPI

Fixed in

8.5.12 · 8.4.27 · 8.3.36 · 8.2.35

Status

Patched · exploit demonstrated

On this page

1. [What to do, in order](#what-to-do-in-order)
2. [The two vulnerabilities](#the-two-vulnerabilities)
3. [Who is exposed](#who-is-exposed)
4. [Exploitation status](#exploitation-status)
5. [If you cannot patch today](#if-you-cannot-patch-today)
6. [Detection and verification](#detection-and-verification)
7. [Why the score alone will not rank this](#why-the-score-alone-will-not-rank-this)
8. [Timeline](#timeline)

On 21 October 2026 the PHP project released PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35 to fix two critical flaws in the PHP engine, tracked as **CVE-2026-109618** and **CVE-2026-109619** and widely nicknamed PHP2Shell. Both are rated 9.2 under CVSS v4.0. Both can be reached by an unauthenticated HTTP request. On Apache with mod\_php, the PHP project has [demonstrated remote code execution](https://www.php.net/archive/2026.php#2026-10-21-5) triggered before any application code runs, which means the application on top does not matter: a WordPress site, a Laravel API and a twenty-year-old in-house tool are exposed the same way.

The PHP project is unusually direct about the response: updating is the only complete fix, and the configuration workarounds it publishes “reduce exposure to specific attack paths but do not make an installation safe”.

## What to do, in order

1. **Find every PHP runtime that answers on the internet.** Start with Apache mod\_php, then PHP-FPM, php-cgi, FrankenPHP and LiteSpeed. Include appliances and vendor products that embed PHP, and container images built on a PHP base.
2. **Update** to 8.5.12, 8.4.27, 8.3.36 or 8.2.35, or to your distribution’s patched package, then **restart every worker**. An upgraded package with running workers leaves the vulnerable code in memory.
3. **If you cannot patch today**, apply the [configuration mitigations](#if-you-cannot-patch-today) below, knowing that they close specific paths and not the vulnerabilities.
4. **Verify** the version that each running server reports, not the PHP command-line binary, and [review logs](#detection-and-verification) from 20 October onwards.

## The two vulnerabilities

|  | CVE-2026-109618 | CVE-2026-109619 |
| --- | --- | --- |
| **PHP advisory** | [GHSA-w8hw-w9fx-j79w](https://github.com/php/php-src/security/advisories/GHSA-w8hw-w9fx-j79w), “RCE via OOM corruption” | [GHSA-6wmf-4rv5-p3rp](https://github.com/php/php-src/security/advisories/GHSA-6wmf-4rv5-p3rp), “RCE via stale global state” |
| **Class** | Memory corruption after an out-of-memory abort | Use-after-free across requests in the same worker |
| **Trigger** | Crafted request, typically multipart, that exhausts memory mid-initialisation | A request that leaves stale state, then a later request on the same worker that uses it |
| **RCE confirmed by PHP** | Apache mod\_php, over HTTP | mod\_php and PHP-FPM via session upload progress; mod\_php via PHP 8.5 fatal error backtraces |
| **CVSS v4.0** | 9.2 | 9.2 |

**CVE-2026-109618, out-of-memory corruption.** PHP handles running out of memory by jumping straight out of the current operation (`longjmp()`). In some places, request memory is already reachable before it is fully initialised. If an allocation fails at that moment, the half-built state stays behind, and request shutdown later reads or branches on it as if it were valid. The attacker’s task is to make PHP run out of memory at the right point, and [the advisory](https://github.com/php/php-src/security/advisories/GHSA-w8hw-w9fx-j79w) lists several ways to do that while staying inside normal limits:

- A request body without a usable declared length can pass the initial `post_max_size` check.
- A single multipart part can carry an unlimited number of headers.
- Empty file fields do not count towards `max_file_uploads` but still create metadata arrays, and nested field names multiply the work.

**CVE-2026-109619, stale state between requests.** A persistent PHP worker keeps some global state (errors, sessions, objects, extension data) across requests, and some of it points into memory owned by a single request. That state has to be cleared before the request’s memory is freed. When a fatal error aborts an operation before its clean-up runs, the pointer survives, and the next request on the same worker can use freed memory before normal initialisation resets it. PHP confirmed two paths: **session upload progress**, which is enabled by default, and on PHP 8.5, **fatal error backtraces**. Exploitation needs a “producer” request and a “consumer” request to be handled by the same worker.

The two compose: an out-of-memory error during multipart parsing, the core of the first flaw, is one of the confirmed ways to leave behind the stale session state the second one consumes.

## Who is exposed

The PHP project considers [every installation serving web requests](https://www.php.net/archive/2026.php#2026-10-21-5) at risk. How directly depends on the server API (SAPI) that runs PHP:

| SAPI | What the PHP advisories confirm | Priority |
| --- | --- | --- |
| **Apache mod\_php** | RCE demonstrated over HTTP, unauthenticated, before any application code runs | Patch first |
| **PHP-FPM** | CVE-2026-109619 RCE validated through session upload progress, conditional on an application operation an attacker can make fail. CVE-2026-109618 susceptible by source analysis; no complete exploit shown | Patch now |
| **php-cgi, FrankenPHP, LiteSpeed** | Listed as at risk; FrankenPHP and LiteSpeed considered likely susceptible but not validated | Patch now |
| **Command line only** (cron, queue workers, build tools) | Outside the web request paths the advisories describe | Normal update cycle |

**Versions.** Every PHP release before the fixed versions is affected. PHP 8.1 and older no longer receive releases from the PHP project; its security team has published minimal source backports for the 7.4, 8.0 and 8.1 branches, and Linux distributions and long-term-support vendors received the patches in advance. Some third-party write-ups claim that every version since PHP 5 is affected. The PHP advisories do not confirm a lower bound, so treat any end-of-life PHP as vulnerable unless its vendor says otherwise.

**Distribution packages.** Enterprise distributions backport fixes without changing the upstream version number, so a version string alone misleads in both directions: an old-looking `8.0.30` can be patched, and a current-looking build from a third-party repository may not be. Go by your vendor’s errata. On release day, [AlmaLinux](https://almalinux.org/blog/2026-10-21-php2shell-cve-2026-109618-cve-2026-109619/) was still building packages, and the PHP project warned that the Remi repository would not have updates the same day. [Red Hat](https://access.redhat.com/security/cve/cve-2026-109618) rates CVE-2026-109618 Important (CVSS v3.1 8.1) rather than critical, because the default PHP-FPM setup on its platforms makes exploitation harder; AlmaLinux notes that its versions 9 and 10 do not ship mod\_php at all.

## Exploitation status

As of 21 October 2026:

- **An exploit has been demonstrated.** The PHP project [demonstrated](https://www.php.net/archive/2026.php#2026-10-21-5) unauthenticated remote code execution against Apache with mod\_php. [Red Hat](https://access.redhat.com/security/cve/cve-2026-109618) notes that reliable exploitation requires precise heap manipulation and timing.
- **Not yet on CISA’s list.** CISA’s [Known Exploited Vulnerabilities catalog](https://www.cisa.gov/known-exploited-vulnerabilities-catalog) did not list either CVE in its 21 October update. That means no confirmed exploitation had been published, not that no one is trying.
- **Be careful with exploit code.** Do not run proof-of-concept code from unknown sources on production or analyst machines; fake exploits are a common lure after a high-profile disclosure.

**Our assessment:** with the fixes public, an exploit already demonstrated by the PHP project and the number of PHP servers on the internet, treat internet-facing PHP as a target and run the update as an emergency change, not as part of the next maintenance window.

## If you cannot patch today

Set these in `php.ini`, a `php.d` drop-in, the FPM pool or the server configuration (not with `ini_set()` or `.user.ini`, which the advisories say not to rely on), then **restart every worker**:

```ini
; CVE-2026-109619: blocks the confirmed session upload progress path.
; Keep it off after patching if no application uses upload progress.
session.upload_progress.enabled = 0

; CVE-2026-109619, PHP 8.5 only: blocks the fatal error backtrace path.
fatal_error_backtraces = 0

; CVE-2026-109618: removes PHP's own memory-limit failure. Enforce it so
; applications cannot set it back (php_admin_value in the FPM pool).
memory_limit = -1

; Keep request bodies small: 8M without uploads, 32M with them,
; with upload_max_filesize below post_max_size.
post_max_size = 8M
```

For PHP-FPM, the same in the pool configuration, plus an optional setting that breaks the same-worker requirement of CVE-2026-109619 at a real cost in throughput:

```ini
php_admin_value[memory_limit] = -1
php_admin_flag[session.upload_progress.enabled] = off
pm.max_requests = 1
```

Know what each of these does not do:

- **`memory_limit = -1` removes a safety net.** Put a container or cgroup memory limit (`memory.max`) behind it, ideally with a policy that kills only the affected worker. Do **not** use `RLIMIT_AS` or `RLIMIT_DATA` (`ulimit -v`, `ulimit -d`) instead: they make allocations fail, which triggers the vulnerable path. An underlying allocation failure can still reach that path even with no PHP limit.
- **Filter at the edge.** At the reverse proxy or WAF, cap the decoded request size, the number of input fields, multipart parts, headers per part and nesting depth, including chunked requests with no usable `Content-Length`. If an application never accepts uploads, block `multipart/form-data` to it entirely.
- **Remove start-up warnings.** Invalid or deprecated per-directory settings (`.htaccess`, `php_value`, `PHP_VALUE`) that emit diagnostics at request start feed CVE-2026-109619. Hiding them with `error_reporting`, `display_errors` or `@` does not help; fix or remove them.
- **Fix reachable fatal errors.** Attacker-triggerable fatal errors and execution timeouts, in upload and import handling, callbacks and clean-up code, are producer paths for the second flaw.
- **On Enterprise Linux 8 with mod\_php**, AlmaLinux recommends moving back to the event MPM with PHP-FPM.

If your WAF or intrusion prevention vendor has shipped signatures for these CVEs, they buy time; they do not change the conclusion.

## Detection and verification

**Check the version that serves requests.** `php -v` reports the command-line binary, which can differ from the one serving traffic. Check the FPM binary (`php-fpm -v`, or `php-fpm8.3 -v` on Debian-family systems), the package that provides Apache’s PHP module, or a temporary `phpinfo()` page behind authentication, removed afterwards. Rebuild container images from a patched base image: a running container keeps the PHP it was built with.

**Look from the outside.** With PHP’s default `expose_php = On`, many servers announce their version in the `X-Powered-By` response header. That gives a fast first list, but it misses servers that hide the header and shows pre-backport version numbers, so it is a starting point, not a verdict. Set `expose_php = Off` once you are done.

**Hunt.** The PHP project had not published indicators of compromise at the time of writing; the signals below follow from how the flaws work. The PHP advisory recommends auditing with `log_errors` on, an `error_log` set and `error_reporting = E_ALL` in the start-up configuration. Review from 20 October onwards:

- `Allowed memory size of … bytes exhausted` fatal errors reported `in Unknown on line 0`, meaning they occurred while parsing the request, before any script ran, particularly from unauthenticated clients or on endpoints that take no uploads.
- Worker crashes: `exit signal Segmentation fault (11)` in the Apache error log, or `exited on signal 11 (SIGSEGV)` in the PHP-FPM log.
- Multipart POST requests with unusually many part headers, many empty file fields or deeply nested field names, or carrying a `PHP_SESSION_UPLOAD_PROGRESS` field to endpoints that do not handle uploads.
- After any crash: unexpected child processes of the web server user, new files under the web root, and outbound connections from web workers.

## Why the score alone will not rank this

Both CVEs carry the same score from the same vector (`AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H`). The vector already records that exploitation is complex and has preconditions. What it cannot record is that the same flaw is application-independent code execution on a mod\_php server and a conditional chain on an FPM pool, or that one of your PHP hosts is the customer portal and another a forgotten staging box. Ranked by CVSS, every PHP host lands in the same bucket. Ranked by what is internet-reachable, which SAPI runs it and what sits behind it, the order of work becomes obvious. Our [CVSS vs EPSS](https://panop.io/cvss-vs-epss/) page develops that argument in general.

Panop’s [discovery](https://panop.io/discovery-product/) starts from a company name, finds the services you expose and fingerprints what they run. For an advisory like this one, the first step above becomes a filter on an inventory you already have, not a search under time pressure. [Request a scan](https://panop.io/trial/) to see where PHP answers on your perimeter.

## Timeline

| Date | Event |
| --- | --- |
| 20 Oct 2026 | PHP announces a critical security release for 21 October, 14:00 UTC; the [advance notice](https://www.openwall.com/lists/oss-security/2026/10/20/34) is relayed on oss-security. Distributions and long-term-support vendors receive the patches in advance. |
| 21 Oct 2026 | PHP publishes 8.5.12, 8.4.27, 8.3.36 and 8.2.35 with advisories GHSA-w8hw-w9fx-j79w and GHSA-6wmf-4rv5-p3rp. |
| 21 Oct 2026 | CISA’s Known Exploited Vulnerabilities catalog update does not list either CVE. |

This advisory reflects public information as of 21 October 2026.

## Sources

1. [PHP security advisory and releases, 21 October 2026](https://www.php.net/archive/2026.php#2026-10-21-5) PHP
2. [GHSA-w8hw-w9fx-j79w: RCE via OOM corruption (CVE-2026-109618)](https://github.com/php/php-src/security/advisories/GHSA-w8hw-w9fx-j79w) PHP
3. [GHSA-6wmf-4rv5-p3rp: RCE via stale global state (CVE-2026-109619)](https://github.com/php/php-src/security/advisories/GHSA-6wmf-4rv5-p3rp) PHP
4. [Upcoming Critical PHP Security Release (advance notice), 20 October 2026](https://www.openwall.com/lists/oss-security/2026/10/20/34) oss-security
5. [CVE-2026-109618](https://access.redhat.com/security/cve/cve-2026-109618) Red Hat
6. [php2shell (CVE-2026-109618, CVE-2026-109619): Patches in progress](https://almalinux.org/blog/2026-10-21-php2shell-cve-2026-109618-cve-2026-109619/) AlmaLinux
7. [Known Exploited Vulnerabilities catalog](https://www.cisa.gov/known-exploited-vulnerabilities-catalog) CISA

About the author

[Panop Research](https://panop.io/company)

Security research team, Panop SA

Panop Research is the security research function of Panop SA, a Swiss exposure management company founded in July 2024 by three practitioners with nearly twenty years each inside large international organisations. It publishes analysis built on primary public datasets, with every figure attributed and linked to the publisher that produced it.

- [LinkedIn](https://www.linkedin.com/company/panop-io)

[← Back to threat intelligence](https://panop.io/threat-intelligence/)

Panop discovers your internet-facing services and fingerprints what they run. Find out where PHP answers on your perimeter.

[Request a scan](https://panop.io/trial)

[All advisories →](https://panop.io/threat-intelligence/)
