PHP critical release: defensive telemetry during reported active exploitation
PHP has shipped fixes for CVE-2026-109618 and CVE-2026-109619. What the advisories confirm, where vendor packages stand, and what the YARA rules can and can’t see.
contents
Warning Update, 21 October 2026. PHP has released 8.5.12, 8.4.27, 8.3.36 and 8.2.35, fixing both vulnerabilities [1]. Update now. PHP’s own position is that there are no complete mitigations and updating is the only safe choice [1, 2, 3]. Cloudflare and hosting providers have publicly reported early attacks and exploitation attempts [5, 6]. On 20 October I reported credible private indications of active exploitation. That remains a first-hand report from me, not independently verifiable public evidence, and I am still withholding locations, evidence and exploit details.
This page started as a pre-patch bulletin. It now reflects PHP’s published advisories, which supersede every pre-release claim, including mine.
What PHP has confirmed #
- Two critical vulnerabilities, each rated CVSS v4.0 9.2, that can allow unauthenticated remote code execution [1].
- CVE-2026-109618, “RCE via OOM corruption” (GHSA-w8hw-w9fx-j79w) [2], and CVE-2026-109619, “RCE via stale global state” (GHSA-6wmf-4rv5-p3rp) [3].
- Fixed in 8.5.12, 8.4.27, 8.3.36 and 8.2.35 [1].
- At risk: all PHP installations serving web requests, including PHP-FPM, Apache with mod_php, php-cgi, FrankenPHP and LiteSpeed. PHP considers the risk highest for mod_php, where an unauthenticated request triggered the attack before any application code ran [1].
- PHP 8.1 and older no longer get upstream releases. PHP published minimal source backports for 7.4, 8.0 and 8.1 for people building from source, and points everyone else at their distribution or LTS vendor [1].
The two bugs #
CVE-2026-109618. PHP exits some out-of-memory conditions with longjmp(). If an allocation fails while request memory is only partly initialized, request shutdown can later read or branch on that invalid state [2]. The advisory describes several multipart parsing behaviors that let a request run PHP out of memory while staying inside its apparent limits, and notes that application-specific allocations can get there too [2]. Validation differs by SAPI. Full unauthenticated RCE was demonstrated over HTTP against mod_php with default input and memory limits. Source analysis supports FPM as susceptible, but no complete FPM exploit was demonstrated. FrankenPHP is described as likely susceptible, and LSAPI as likely but unvalidated [2].
CVE-2026-109619. Request-owned error, session, object or extension state can stay reachable from worker globals after the request’s memory is freed. A later request on the same worker can use that stale state before normal initialization resets it [3]. Exploitation needs a producer, such as a fatal error, memory exhaustion, a failed require or an execution timeout, and an early consumer. PHP confirms two consumers: INI diagnostics raised before request initialization, and session upload progress [3]. The fatal-backtrace path is confirmed RCE against mod_php. The session-lifecycle path was validated against mod_php and FPM, and on FPM it depended on a suitable application operation. Producer and consumer have to hit the same worker; more workers and recycling lower the odds per attempt but don’t remove the bug [3].
How the pre-release picture held up #
Before release, the strongest public hypothesis was upload progress and multipart handling, most specifically from the group that published the php-up-2026 proof of concept [12]. That was part right and incomplete. Session upload progress is a confirmed early consumer in CVE-2026-109619, and multipart parsing supplies confirmed out-of-memory strategies for CVE-2026-109618. Neither CVE is limited to upload progress, and turning it off never fully mitigated either vulnerability. It does block confirmed session paths for CVE-2026-109619. PHP has not published an affected-version statement going back to PHP 5; the “every version since 5.4” claim came from third-party reporting [9, 10] and remains unconfirmed by the vendor.
Distribution and vendor packages #
PHP says distributions and LTS vendors received the patches in advance [1]. Distribution packages often backport fixes without moving to the upstream version number, so check the vendor’s tracker for the CVE, not the version string.
Status checked 21 October 2026, 14:20 to 14:35 UTC.
| Vendor | Branch | Status | Source |
|---|---|---|---|
| PHP (Windows builds) | 8.2 to 8.5 | Fixed builds posted | windows.php.net (opens in a new tab) |
| Ubuntu | 26.10, 26.04 LTS, 24.04 LTS, 22.04 LTS | Fixed by backport: 8.5.9-0ubuntu2.1, 8.5.4-0ubuntu1.5, 8.3.6-0ubuntu0.24.04.13, 8.1.2-1ubuntu2.28 (USN-8948-1) |
ubuntu.com (opens in a new tab) |
| Ubuntu | 20.04 and older (ESM) | Needs evaluation | ubuntu.com (opens in a new tab) |
| Debian | 11, 12, 13 | No tracker entry and no DSA or DLA yet | security-tracker.debian.org (opens in a new tab) |
| Sury (packages.sury.org, Debian) | bullseye, bookworm, trixie | Upstream fixed versions published (8.2.35, 8.3.36, 8.4.27, 8.5.12) | packages.sury.org (opens in a new tab) |
| Sury (Launchpad PPA, Ubuntu) | noble, jammy | Not yet; still 8.2.34 to 8.5.11 | launchpad.net (opens in a new tab) |
| Red Hat Enterprise Linux | 8, 9, 10 | No CVE record or erratum yet | access.redhat.com (opens in a new tab) |
| AlmaLinux, Rocky Linux | 8, 9, 10 | No erratum yet | errata.almalinux.org (opens in a new tab), apollo.build.resf.org (opens in a new tab) |
| Oracle Linux | 8, 9, 10 | Could not be verified | linux.oracle.com (opens in a new tab) |
| Amazon Linux | AL2, AL2023 | No ALAS yet | explore.alas.aws.amazon.com (opens in a new tab) |
| SUSE, openSUSE | all | No CVE page yet | suse.com (opens in a new tab) |
| Fedora | 43, 44 | Not yet; rawhide has an 8.5.12 release candidate only | mdapi.fedoraproject.org (opens in a new tab) |
| Remi (rpms.remirepo.net) | EL8, EL9 | In progress. PHP said Remi would not update today [1], but fixed builds (8.2.35, 8.3.36, 8.4.27, 8.5.12) are appearing in the repository. On EL8, php-fpm-8.3.36 was present in the modular repository metadata while dnf check-update on the php:remi-8.3 stream still offered only 8.3.35 at 14:35 UTC. No Remi announcement found. |
rpms.remirepo.net (opens in a new tab) |
| Alpine | edge, 3.20 to 3.24 | No secdb entry and no fixed builds yet | secdb.alpinelinux.org (opens in a new tab) |
| Arch Linux | rolling | Fixed in php 8.5.12-1 (AVG-2909) |
security.archlinux.org (opens in a new tab) |
Docker official php image |
all tags | Fix merged upstream; fixed tags not published to Docker Hub yet | github.com/docker-library/php (opens in a new tab) |
| Homebrew | php and the versioned 8.2 to 8.4 formulae | Update pull requests open, not merged | formulae.brew.sh (opens in a new tab) |
| cPanel EasyApache 4 | ea-php82 to ea-php85 | No update or notice found | docs.cpanel.net (opens in a new tab) |
| Plesk | Linux 8.2 to 8.5 | Patched; 7.4, 8.0 and 8.1 pending; all Windows versions pending | support.plesk.com (opens in a new tab) |
| CloudLinux alt-php | 8.2 to 8.5 | No fixed packages found; Imunify360 ruleset 8.83 announced | blog.cloudlinux.com (opens in a new tab) |
| LiteSpeed lsphp | 8.2 to 8.5 | No fixed packages found | rpms.litespeedtech.com (opens in a new tab) |
This changes by the hour. “Not yet” means the vendor had published nothing at check time, not that a package is unaffected.
If you can’t update yet #
None of this makes an installation safe [1]. These are PHP’s own partial measures, for systems that can’t take the update immediately.
- Set
memory_limit=-1where applications can’t override it, for example withphp_admin_valuein the FPM pool or Apache configuration, then check that no pool, directory or application setting puts a finite limit back. It removes the controllable memory-limit failure. An underlying allocation failure can still reach the bug. - Unlimited memory per request is an availability risk. PHP recommends a container or cgroup limit as the availability boundary, ideally one that kills only the affected worker. Do not use
RLIMIT_ASorRLIMIT_DATA; they can cause the vulnerable allocation failure. - Lower
post_max_size: PHP suggests 8M for applications without uploads and 32M with them, withupload_max_filesizebelow it. - At the web server or proxy, bound decoded request size, input field count, multipart part count, header count and nesting depth, including for requests without a usable
Content-Length. If an application doesn’t use multipart form data, block it before it reaches PHP.
- Set
session.upload_progress.enabled=0inphp.ini, an FPM pool or server configuration that applies before request parsing, and restart every worker. Don’t rely onini_set()or FPM.user.ini. This blocks the confirmed session paths, not other variants. PHP suggests leaving it off after patching too if you don’t use the feature [3]. - On PHP 8.5 only, set
fatal_error_backtraces=0and restart every worker. This blocks the confirmed fatal-backtrace path only. - Remove invalid or deprecated per-request INI settings that emit diagnostics before initialization. Hiding diagnostics with
error_reporting,display_errorsor@does not help. - Fix attacker-reachable fatal errors and execution timeouts, including in upload, import, callback and cleanup paths.
After any of these, and after the update itself, confirm the serving workers were actually replaced. Installing a package doesn’t change processes that are already running.
Exploitation status #
Cloudflare’s CTO said on 21 October that Cloudflare was “seeing early attacks emerging” and had deployed WAF rules for the known vectors to all plans, including free, as a stopgap [5]. Those rules only help an origin that accepts traffic exclusively from Cloudflare [6]. Patchstack reported “multiple active exploitation incidents” from hosting partners, while its own telemetry at 13:57 UTC showed “only probing attacks, with no hard evidence of breaches yet” [6]. Huntress had not seen in-the-wild exploitation in partner environments as of 20 October [7].
Active probing and apparent exploitation attempts have been reported by named operators. Public reporting does not yet establish how many systems, if any, were successfully compromised through these CVEs, and there is no public, corroborated campaign IOC set.
Defender hunt #
The advisories confirm paths that may leave no upload-progress or multipart artifact at all, so post-compromise behavior now matters more than request shape. Look for:
- PHP-FPM, Apache, LiteSpeed or FastCGI workers spawning shells, interpreters, download tools, networking tools or reconnaissance commands.
- Worker crashes, restarts and segfaults, and clusters of 5xx responses or upstream resets on PHP-backed routes.
- Repeated fatal errors, out-of-memory errors and
Maximum execution time exceededon attacker-reachable routes. PHP’s CVE-2026-109619 advisory includes a logging audit list for exactly this [3]. - Unusual multipart traffic: very large or deeply nested field names, many headers per part, many empty file controls, or requests without a usable
Content-Length. - New or modified files in the web root, changed startup and scheduled-task files, and outbound connections from the PHP service account.
None of these proves exploitation alone. Correlate them, and preserve request records, process trees, command lines, network events, PHP and web-server logs, and worker crash and restart history. Existing EDR rules for web servers spawning shells already cover the post-exploitation step whatever the entry point: Elastic’s Linux rule includes php-fpm*, php-cgi and lsphp* parents [13], and its Windows rule covers php.exe and php-cgi.exe [14]. Match php-fpm as a prefix, because Debian-family workers run as php-fpm8.2 and similar.
YARA #
These rules hunt the publicly circulated research artifacts, upload-progress session records, retained multipart request bodies and command-payload strings in session artifacts. They do not comprehensively detect CVE-2026-109618 or CVE-2026-109619. The advisories confirm other out-of-memory and stale-state paths that may leave none of these artifacts. A clean scan does not establish that a host was not targeted or compromised.
The ruleset is also available as a download: php-upload-progress-prepatch-defense.yar.
| Rule group | What it covers | Confidence |
|---|---|---|
| Exact archive hash | One unchanged copy of the PoC group’s published archive | High, for that exact file only; not a compromise verdict |
| Unpacked tooling strings | Files associated with the PoC group’s tooling | Medium; documentation and copied snippets also match |
| Potential command-payload residue | Command-payload strings in session artifacts | Medium; may represent an attempted or staged payload and does not prove execution |
| Small multipart progress requests | Selected request shapes, not every CVE-2026-109618 strategy | Low |
| Session progress records | A confirmed CVE-2026-109619 consumer surface, not the whole bug | Informational |
| Any progress field | Baseline feature use | Informational |
YARA inspects retained artifacts. It cannot see connection timing, worker crashes, PHP memory state, or requests that were never logged. Do not use the informational or low-confidence rules as blocking conditions. Scan retained, decrypted request bodies and copied session data or backups rather than live session files, unpack archives first, exclude rule, documentation, threat-intelligence and fixture directories to avoid self-matches, and record the YARA version, command line, corpus and results with each scan. The small-file rule’s filesize < 4096 condition applies to the retained artifact passed to YARA, not necessarily the original wire-level request.
/*
* Defensive telemetry originally published before the 2026 PHP emergency release.
* Post-release advisories confirm broader OOM and stale-state paths that these
* rules do not comprehensively detect.
*
* Scope:
* - Scan UNPACKED files and retained, decrypted HTTP request bodies.
* - These rules are alerts/hunts, not a compensating control for a PHP-core flaw.
* - Do not scan live session files in place if the scanner can lock or alter them.
*/
import "hash"
rule PHPUP_Staged_Bundle_Exact_Hash
{
meta:
author = "gib.bz"
date = "2026-10-20"
confidence = "high"
purpose = "Detect the exact staged archive identified in public reporting"
limitation = "Hash only; renamed or modified variants will not match"
condition:
filesize > 30MB and filesize < 50MB and
hash.sha256(0, filesize) == "0c254d547cac650bfbcb2275e30c2083737520a51a0511646f1fbb7ed60a0d63"
}
rule PHPUP_Staged_Tooling_Unpacked
{
meta:
author = "gib.bz"
date = "2026-10-20"
confidence = "medium"
purpose = "Hunt unpacked staged-tooling files or documentation"
limitation = "Compressed tarballs must be unpacked before string scanning"
strings:
$file1 = "php_up_framework.py" ascii wide
$file2 = "poc0_109618.py" ascii wide
$file3 = "poc1_109619.py" ascii wide
$file4 = "poc_trigger.py" ascii wide
$mark1 = "DELTAS_LSphp" ascii wide nocase
$mark2 = "PHPUP_FILES" ascii wide
$mark3 = "php_session_rfc1867_callback" ascii wide
condition:
filesize < 10MB and (2 of ($file*) or (1 of ($file*) and 1 of ($mark*)))
}
rule PHPUP_Session_Progress_Record
{
meta:
author = "gib.bz"
date = "2026-10-20"
confidence = "informational"
purpose = "Locate persisted upload-progress records for incident scoping"
limitation = "Matches normal use of the feature; supports common PHP serializers only"
strings:
$php_session = /upload_progress_[^|]{0,256}\|a:[0-9]{1,10}:\{/ ascii
$php_serialize = /s:[0-9]{1,10}:"upload_progress_[^"]{0,256}";a:[0-9]{1,10}:\{/ ascii
$field1 = "bytes_processed" ascii
$field2 = "content_length" ascii
$field3 = "start_time" ascii
$field4 = "files" ascii
condition:
filesize < 4MB and (any of ($php_*) and 2 of ($field*))
}
rule PHPUP_Session_Progress_Potential_PostCompromise
{
meta:
author = "gib.bz"
date = "2026-10-20"
confidence = "medium"
purpose = "Triage session artifacts that contain progress data and command-payload strings"
limitation = "May be an attempted or staged payload; a match does not prove execution or compromise"
strings:
$progress = "upload_progress_" ascii
$cmd1 = "system(" ascii nocase
$cmd2 = "shell_exec" ascii nocase
$cmd3 = "proc_open" ascii nocase
$cmd4 = "passthru" ascii nocase
$cmd5 = "/bin/sh" ascii
$cmd6 = "/dev/tcp/" ascii
$cmd7 = /(curl|wget)\s+-?[a-zA-Z]*\s*https?:\/\// ascii
condition:
filesize < 4MB and $progress and 1 of ($cmd*)
}
rule PHPUP_Multipart_Progress_Small_File_Hunt
{
meta:
author = "gib.bz"
date = "2026-10-20"
confidence = "low"
purpose = "Prioritize retained multipart requests that exercised upload progress with a very small file part"
limitation = "Use for hunt/correlation only; legitimate upload-progress forms can match"
strings:
$disposition = "Content-Disposition: form-data" ascii nocase
$progress = "name=\"PHP_SESSION_UPLOAD_PROGRESS\"" ascii nocase
$file_part = "filename=" ascii nocase
condition:
filesize < 4096 and all of them
}
rule PHPUP_Multipart_Progress_Any
{
meta:
author = "gib.bz"
date = "2026-10-20"
confidence = "informational"
purpose = "Baseline all retained use of PHP upload progress"
limitation = "Never use alone as a block or high-severity alert"
strings:
$progress = "PHP_SESSION_UPLOAD_PROGRESS" ascii nocase
condition:
$progress
}
Indicators published by the PoC group, not independently verified #
The group that published the php-up-2026 PoC page published an archive hash and file names for its bundle. They describe that published material only. They are not PHP-vendor IOCs and have not been independently validated against observed attacks. A match is a reason to investigate, not proof that a host was compromised. Preserve matching files for incident-response review.
| Type | Indicator | Context | First seen (UTC) |
|---|---|---|---|
| SHA-256 | 0c254d547cac650bfbcb2275e30c2083737520a51a0511646f1fbb7ed60a0d63 |
Archive hash as published by the PoC group; not independently verified | 2026-10-21 |
| File name | php_up_framework.py, poc0_109618.py, poc1_109619.py, poc_trigger.py |
File names listed by the PoC group | 2026-10-21 |
Timeline #
| Time (UTC) | Event | Source |
|---|---|---|
| 2026-10-20 | PHP announces a critical security release for 21 October at 14:00 UTC, two vulnerabilities rated CVSS v4.0 9.2 | [4] |
| 2026-10-20 19:33 | Release announcement posted to the php.announce list | news-web.php.net (opens in a new tab) |
| 2026-10-20 20:56 | BleepingComputer reports the CVE identifiers; watchTowr says it believes it reproduced CVE-2026-109618 and has seen no in-the-wild exploitation | [9] |
| 2026-10-20/21 | CERT-EU publishes advisory 2026-018 recommending isolation of internet-facing PHP applications until fixed (the page shows conflicting publication dates) | [8] |
| 2026-10-21 02:13 | PHP core developer Gina Peter Banyard: “the only mitigation is patching / upgrading PHP” | [11] |
| 2026-10-21 07:34 | Patchstack: multiple active exploitation incidents reported by hosting partners | [6] |
| 2026-10-21 07:43 | Cloudflare CTO: “early attacks emerging”; WAF rules deployed for all plans as a stopgap | [5] |
| 2026-10-21 13:34 | PHP publishes GHSA-6wmf-4rv5-p3rp and GHSA-w8hw-w9fx-j79w | [2, 3] |
| 2026-10-21 13:50 | Arch Linux php 8.5.12-1 reaches the repository |
security.archlinux.org (opens in a new tab) |
| 2026-10-21 13:52 | PHP releases 8.5.12, 8.4.27, 8.3.36 and 8.2.35 (time per Patchstack) | [1, 6] |
| 2026-10-21 13:57 | Patchstack: own telemetry shows only probing, no hard evidence of breaches yet | [6] |
| 2026-10-21 14:01 | Sury’s Debian repository publishes the fixed versions for bookworm and bullseye (trixie at 13:45) | packages.sury.org (opens in a new tab) |
| 2026-10-21 | Ubuntu publishes USN-8948-1 with backported fixes for 22.04 through 26.10 | ubuntu.com (opens in a new tab) |
| 2026-10-21 14:09 | Plesk updates its advisory: Linux PHP 8.2 to 8.5 patched, Windows pending | support.plesk.com (opens in a new tab) |
| 2026-10-21 14:17 | NVD publishes both CVEs (status “Received”) | nvd.nist.gov (opens in a new tab) |
| 2026-10-21 14:20 | Neither CVE is in the CISA Known Exploited Vulnerabilities catalog | cisa.gov (opens in a new tab) |
References #
- PHP, “Security advisory: Critical remote code execution vulnerabilities, update now”, 21 October 2026. php.net (opens in a new tab) (accessed 21 October 2026)
- PHP, “RCE via OOM corruption”, CVE-2026-109618, GHSA-w8hw-w9fx-j79w. github.com (opens in a new tab) (accessed 21 October 2026)
- PHP, “RCE via stale global state”, CVE-2026-109619, GHSA-6wmf-4rv5-p3rp. github.com (opens in a new tab) (accessed 21 October 2026)
- PHP, “Upcoming Critical PHP Security Release”, 20 October 2026. php.net (opens in a new tab) (accessed 20 October 2026)
- Dane Knecht (@dok2001), post on X, 21 October 2026. x.com (opens in a new tab) (accessed 21 October 2026)
- Patchstack, “PHP major vulnerability alert”, timeline updated 21 October 2026. patchstack.com (opens in a new tab) (accessed 21 October 2026)
- Huntress, “Rapid Response: php2shell, Leaked Critical PHP Vulnerabilities (CVE-2026-109618 & CVE-2026-109619)”, 21 October 2026. huntress.com (opens in a new tab) (accessed 21 October 2026)
- CERT-EU, “Critical Vulnerabilities in PHP”, Security Advisory 2026-018. cert.europa.eu (opens in a new tab) (accessed 21 October 2026)
- BleepingComputer, “PHP warns admins of two critical flaws, emergency patches coming tomorrow”, 20 October 2026. bleepingcomputer.com (opens in a new tab) (accessed 20 October 2026)
- Sansec, “Critical PHP RCE: CVE-2026-109618 and CVE-2026-109619”. sansec.io (opens in a new tab) (accessed 20 October 2026)
- Gina Peter Banyard (@Girgias), Mastodon post, 21 October 2026. phpc.social (opens in a new tab) (accessed 21 October 2026)
- @acd421, post on X, 21 October 2026. x.com (opens in a new tab) (accessed 21 October 2026)
- Elastic, “Unusual Command Execution via Web Server” detection rule. github.com (opens in a new tab)
- Elastic, “Web Shell Detection: Script Process Child of Common Web Processes” detection rule. github.com (opens in a new tab)
Corrections #
- Before PHP’s advisories, this page treated session upload progress and multipart handling as the likely vulnerable paths, based on third-party reporting and the PoC group’s hypothesis. PHP’s advisories show two broader root causes, out-of-memory corruption and stale global state. Upload progress is one confirmed consumer for CVE-2026-109619, and multipart parsing supplies out-of-memory strategies for CVE-2026-109618. The page now reflects the advisories. 2026-10-20: The unpacked-tooling YARA rule was published as high confidence. It is medium confidence: documentation and copied snippets can match its strings.