TL;DR
PHP has released emergency fixes for two critical memory-corruption vulnerabilities, CVE-2026-109618 and CVE-2026-109619. Both allow unauthenticated remote code execution on default configurations. Details were leaked before the coordinated disclosure, which forced an accelerated release. Update to PHP 8.5.12, 8.4.27, 8.3.36 or 8.2.35 now.
UPDATE: Now Official With Patch Versions
UPDATE (October 21, 2026 14:00 UTC): PHP has released 8.5.12, 8.4.27, 8.3.36 and 8.2.35, fixing both critical flaws (CVSS 9.2). They are CVE-2026-109618, RCE via OOM corruption (GHSA-w8hw-w9fx-j79w), and CVE-2026-109619, RCE via stale global state (GHSA-6wmf-4rv5-p3rp). Session upload progress is only one confirmed attack path, so disabling it reduces the risk but doesn’t fully mitigate it. Updating is the only complete fix. mod_php is at highest risk. PHP 8.1 and older get no official release, but source backports are available for 7.4, 8.0 and 8.1.
What’s happening?
The bugs live in php_session_rfc1867_callback (ext/session/session.c). PHP caches two zval * pointers (post_bytes_processed and current_file_bytes_processed) into HashTables while tracking multipart upload progress. A second request triggers session re-read and zend_hash_update, which destroys the HashTable via zval_ptr_dtor. The freed memory can then be reclaimed and controlled by the attacker.
How the attack works
An attacker sends a fast multipart POST that populates the cached pointers, followed by a second request that forces the HashTable destruction. After the free, the attacker places a controlled zend_fcall_info / zend_internal_function structure at the reclaimed address. The next use of the dangling pointer reaches zend_call_function, which can be directed at system() or equivalent.
The exploit requires the upload-progress key as a multipart form field (default name PHP_SESSION_UPLOAD_PROGRESS) before a file part. Stock php.ini is sufficient (session.upload_progress.enabled=1). The field name is configurable via session.upload_progress.name, so only the default is a reliable indicator.
Successful exploitation needs a per-build offset between zval_ptr_dtor and zend_call_function. A wrong offset or a lost heap race typically segfaults the PHP worker. When a proxy sits in front (nginx → php-fpm), this produces a 5xx (commonly 502). A correct offset that wins the race returns 200 and executes the payload. mod_php without a proxy often just drops the connection.
Independent research published confirmed the issue on stock PHP 8.4.4 and 8.2.34 and supplied a framework that extracts build-specific offsets, forges the body, and delivers the payload. PHP’s multipart parser is also looser than a simple line-based field matcher: it accepts folded headers, lines with no colon (glued to the previous header), Content-Disposition without form-data, missing spaces, and junk after the closing quote. Detection logic that only looks for a clean name=”PHP_SESSION_UPLOAD_PROGRESS” on a single line can be evaded.
Why this matters
- Default configuration is vulnerable.
- PHP powers a large fraction of the web (WordPress, Drupal, Magento, control panels, shared hosting).
- Successful exploitation yields command execution as the PHP process user.
- End-of-life branches (8.1 and earlier, 7.x, 5.x) will not receive official fixes.
Recommended actions
- Apply the official PHP security release as soon as it is available (targeted for today at 14:00 UTC). Expected fixed versions include the current supported branches (8.2–8.5).
- Immediate mitigation: set session.upload_progress.enabled=0 in php.ini, .user.ini, or .htaccess.
- Inventory every PHP installation (php-fpm, php-cgi, mod_php, control panels, Windows bundles, application-bundled PHP).
- For detection, look for POST requests containing the upload-progress field (accounting for the parser’s loose header handling) and treat 5xx responses from PHP workers as a high-confidence crash signal of an attempted exploit. A 200 on the same pattern is the success case.
- Isolate or upgrade any internet-facing end-of-life PHP.
The bigger picture
These are classic use-after-free bugs in a high-traffic request path. The leak forced an accelerated release, and the technical details (including the precise free and reclaim path plus the need for per-build offsets) are already public. Until systems are patched or the feature is disabled, any exposed PHP process that handles multipart uploads is a candidate for remote code execution.
Bottom line
Two critical use-after-free flaws in PHP’s session upload progress handling allow remote code execution on default configurations. Disable session.upload_progress.enabled now if you cannot patch immediately, apply the official release as soon as it drops, and treat end-of-life PHP as high risk.
