high CVSS 8.1 Actively exploited EPSS 100%

CVE-2026-109619·PHP vulnerability

PHP has various global state that temporarily points into request memory. In some scenarios, global state may not be correctly reset, or may be repopulated after being reset. The global state may then refer to request memory even after it has been freed. Subsequent requests may read or branch on this stale state before it is fully initialized. Multiple strategies can trigger this condition and produce remote code execution (RCE).

Severity
high
Software
PHP
Fixed in
8.2.35 / 8.3.36 / 8.4.27 / 8.5.12 (per branch; PHP 8.1 and older are end-of-life, no official fix)
Published

How likely is exploitation

FIRST's Exploit Prediction Scoring System puts the probability of this CVE being exploited in the next 30 days at 100% — among the highest-scoring CVEs ever published. EPSS is an independent forecast of exploitation, not a severity rating: it says nothing about how much damage a successful attack does, which is what a CVSS score measures.

How to fix this CVE

Update to the patched release for your branch — PHP 8.2.35, 8.3.36, 8.4.27 or 8.5.12 — the only complete fix. php.net: "there are no complete mitigations, updating is the only safe choice." If you cannot update immediately, the documented partial mitigation for THIS CVE is to set session.upload_progress.enabled=0 and restart every worker, applied BEFORE request parsing via php.ini, an FPM pool or server configuration. Do NOT rely on ini_set() or a per-directory .user.ini — they apply too late and a customer can override them. This reduces exposure but is not complete — and on PHP 8.5 there is a second confirmed trigger (the fatal_error_backtraces setting), so disabling upload_progress alone does not close it on 8.5. For versions with no official patch (PHP 5.4–8.1 are end-of-life), a community stopgap exists: Hosted Power's hp_uploadprogress_guard PHP extension (MIT, linked under References), which since v3 carries PHP's fixed multipart parser per branch behind a memory-headroom guard, mirrors the rest of the official fix component by component, and steps aside on a patched engine (8.2.35 / 8.3.36 / 8.4.27 / 8.5.12 and newer) while keeping its non-php2shell fixes active. Since v3.2.0 it also isolates unserialize() re-entrancy (php-src#24481, still open upstream) and since v3.2.1 it carries PHP's approved fix for the SimpleXML crash that 8.4.27 and 8.5.12 introduced (php-src#24488). It covers PHP 5.4 through 8.5, which makes it the only route for end-of-life branches. Checked against the repository on 22 Oct 2026 (v3.2.2). It is a stopgap, not a replacement for upgrading. Note on the fixed releases, verified against php-src on 22 Oct 2026. Upgrading closes this CVE, but two distinct PHP bugs outlive it. php-src#24481 - a use-after-free in var_destroy() during unserialize() re-entrancy - is still OPEN and confirmed present in 8.5.12, 8.4.27, 8.3.36, 8.2.35 and 7.4.33, and it is reachable over HTTP through the same session machinery this CVE abuses (session.serialize_handler=php_serialize alongside upload-progress tracking), so the fixed release does not by itself close the session attack surface. php-src#24488 - a GC double-free of the SimpleXMLElement properties table that aborts the FPM worker on any request JSON-encoding a SimpleXMLElement caught in a collected cycle - was INTRODUCED by 8.4.27 and 8.5.12 (8.4.26 is unaffected); its fix landed in the PHP-8.4, PHP-8.5 and PHP-8.6 branches on 22 Oct 2026 but has not shipped in a release yet. Patch regardless: this CVE is remote code execution and a worker crash is not. Then track both issues.

sudo apk update && sudo apk upgrade php82 php82-fpm (match your version prefix), then sudo rc-service php-fpm82 restart. Confirm the patched build is in your release branch before relying on it.

Defensia detects this vulnerability

Rules:ModSecurity 9910015 (inline, Apache with SecRequestBodyAccess On) - denies the known upload_progress exploit shape; Defensia agent v1.4.81+. Partial detector, not a complete block.
Monitored by:weblog (relays the ModSecurity block; does not inspect bodies)

What an exploitation attempt looks like

Sample log line indicative of exploitation attempts:

POST / HTTP/1.1  Content-Type: multipart/form-data; boundary=X  — a part named PHP_SESSION_UPLOAD_PROGRESS drives the handler while the same PHPSESSID is replayed across two endpoints whose directories declare different session.serialize_handler values (php vs php_serialize), with a serialized-object payload in the upload filename, e.g. filename="|O:4:\"Evil\":1:{s:3:\"cmd\";s:2:\"id\";}". The access log shows only a multipart POST: the discriminating content is in the request body, which access logs do not record. Only an inline WAF with request-body access (Apache + ModSecurity, phase 2) can see it; a log-based engine cannot.

WAF mitigation (if patching is not yet possible)

Add this rule to your WAF to block exploitation attempts while you schedule the patch.

This is the one path here a WAF can address: a ModSecurity rule (Apache, inline) that denies a multipart request driving PHP_SESSION_UPLOAD_PROGRESS while carrying a serialized object or PHP tag in a filename. (It does NOT address the companion CVE-2026-109618, whose trigger is memory exhaustion with no distinctive payload — see that advisory.)

SecRequestBodyAccess On
SecRule ARGS_NAMES "@streq PHP_SESSION_UPLOAD_PROGRESS" \
  "id:2026109619,phase:2,deny,status:403,log,t:none,\
   msg:'CVE-2026-109619 PHP upload_progress UAF/deserialization attempt',chain"
  SecRule FILES_NAMES|ARGS:PHPSESSID "@rx (?i)(?:\|O:[0-9]+:|<\?php|php_serialize|<\?=)" "t:none"

Because 109619 is a memory-corruption/deserialization chain, a signature is a time-buying stopgap only. On nginx + php-fpm the body reaches PHP before a log-based engine sees it, so there the control is detection, not blocking — and php-fpm is itself vulnerable (php.net confirmed RCE on it), not just mod_php. Patch to the fixed release — that is the only reliable fix.

How to check if you are affected

  1. Confirm your PHP version/branch: php -v and php-fpm8.x -v. 5.4.0–8.5.x before the release-day fix are affected.
  2. Check the handler state (ON by default): php -i | grep -i session.upload_progress.
  3. Look for directories that declare different session serializers (a precondition for the handler-mismatch chain): grep -rs 'session.serialize_handler' /etc/php* /var/www --include=.user.ini --include=php.ini 2>/dev/null — mixed php and php_serialize values across paths sharing one save_path is the risky layout.
  4. Grep the session save path for serialized objects or PHP tags: grep -rIl -e '<?php' -e 'O:[0-9]' $(php -r 'echo ini_get("session.save_path") ?: "/var/lib/php/sessions";') 2>/dev/null.
  5. Watch for php-fpm worker crashes/segfaults (dmesg, the FPM error log) around multipart POST bursts — a sign of the UAF being exercised — and for the web user spawning shells or writing new PHP files.

Indicators of compromise

  • php-fpm worker segfaults or 'SIGSEGV' / 'child exited on signal 11' entries in the FPM error log correlated with multipart POSTs.
  • Session files under the save path containing serialized object markers 'O:<n>:' or PHP open tags.
  • The same PHPSESSID replayed across two endpoints with different session.serialize_handler settings.
  • Multipart POSTs carrying PHP_SESSION_UPLOAD_PROGRESS with a body-supplied PHPSESSID rather than a cookie.
  • Web user (www-data, nginx, apache, php-fpm) spawning sh/bash/curl/wget or new PHP files appearing under the web root after release day.
  • Multipart/form-data POSTs immediately followed by PHP memory-limit errors or repeated HTTP 500 responses from the same endpoint (Wiz).
  • Unexpectedly large or malformed PHPSESSID response cookies.
  • Unexplained PHP-FPM worker churn — workers recycling or restarting with no obvious cause.

FAQ

How is this different from CVE-2026-109618?

They share the same upload_progress/multipart entry point and were disclosed together. 109618 is about session fixation and raw filename injection landing attacker content on disk; 109619 is the memory-safety and deserialization side — a heap use-after-free in var_destroy and a cross-request serializer leak that enables object injection. Patch both at once; the fixed PHP release closes both.

Is this only exploitable on Apache with mod_php?

No. The handler runs under FPM too; the public analysis confirms the serializer leak specifically in FPM. Reliability varies with SAPI and heap layout, but treat any PHP 5.4–8.5 deployment as affected until patched.

I'm on an EOL branch (7.x / 8.0 / 8.1). What now?

No official patch will be issued. Upgrade to a supported 8.2+ branch. A body-inspecting WAF (ModSecurity inline on Apache) is a stopgap; on nginx + php-fpm you get detection but not reliable blocking.

Does disabling upload_progress stop this one too?

It reduces exposure by closing the shared entry point, but PHP core developers are explicit that patching is the only complete mitigation. Use session.upload_progress.enabled = Off and session.use_strict_mode = On to buy time, then patch.

Can I detect exploitation attempts?

Yes — watch for php-fpm segfaults around multipart POST bursts, serialized objects or PHP tags appearing in session files, and the web user spawning shells. The detection steps above give the exact commands.

Related PHP CVEs

CVE-2026-28289CVSS 10FreeScout is a free help desk and shared inbox built with PHP's Laravel framework. A patch bypass vulnerability for CVE-2026-27636 in FreeScout 1.8.206 and earlier allows any authenticated user with file upload permissions to achieve Remote Code Execution (RCE) on the server by uploading a malicious .htaccess file using a zero-width space character prefix to bypass the security check. The vulnerability exists in the sanitizeUploadedFileName() function in app/Http/Helper.php. The function contains a Time-of-Check to Time-of-Use (TOCTOU) flaw where the dot-prefix check occurs before sanitization removes invisible characters. This vulnerability is fixed in 1.8.207.
CVE-2025-47916CVSS 10Invision Community 5.0.0 before 5.0.7 allows remote code execution via crafted template strings to themeeditor.php. The issue lies within the themeeditor controller (file: /applications/core/modules/front/system/themeeditor.php), where a protected method named customCss can be invoked by unauthenticated users. This method passes the value of the content parameter to the Theme::makeProcessFunction() method; hence it is evaluated by the template engine. Accordingly, this can be exploited by unauthenticated attackers to inject and execute arbitrary PHP code by providing crafted template strings.
CVE-2024-5932CVSS 10The GiveWP – Donation Plugin and Fundraising Platform plugin for WordPress is vulnerable to PHP Object Injection in all versions up to, and including, 3.14.1 via deserialization of untrusted input from the 'give_title' parameter. This makes it possible for unauthenticated attackers to inject a PHP Object. The additional presence of a POP chain allows attackers to execute code remotely, and to delete arbitrary files.
CVE-2026-39337CVSS 10ChurchCRM is an open-source church management system. Prior to 7.1.0, critical pre-authentication remote code execution vulnerability in ChurchCRM's setup wizard allows unauthenticated attackers to inject arbitrary PHP code during the initial installation process, leading to complete server compromise. The "$dbPassword" variable is not sanitized. This vulnerability exists due to an incomplete fix for CVE-2025-62521. This vulnerability is fixed in 7.1.0.
CVE-2025-25174CVSS 10Improper Control of Filename for Include/Require Statement in PHP Program ('PHP Remote File Inclusion') vulnerability in beeteam368 BeeTeam368 Extensions beeteam368-extensions allows PHP Local File Inclusion.This issue affects BeeTeam368 Extensions: from n/a through <= 1.9.4.

References

Track CVEs across your fleet automatically

Defensia scans your Linux servers and tells you exactly which ones are running vulnerable versions — including CVE-2026-109619. Free for 1 server.

Get started free