Oct 23, 2026·5 min read·9 visits
Unauthenticated remote attackers can trigger an out-of-memory error during PHP request processing, causing non-local longjmp() unwinding that leaves memory structures uninitialized and results in arbitrary code execution during request shutdown.
CVE-2026-109618 (dubbed PHP2Shell) is a critical vulnerability in the PHP engine core resulting from improper out-of-memory exception handling via longjmp(). When request allocation fails mid-processing, non-local control flow bypasses cleanup procedures, leaving memory structures uninitialized or in a use-after-free state during request shutdown.
PHP processes incoming HTTP requests through a structured lifecycle managed by the Zend Engine runtime environment. During request execution, memory allocations are continuously requested from Zend Memory Manager (ZMM) heap pools. To handle allocation failures gracefully without crashing the host process, PHP relies on a central error handling mechanic powered by the standard C library primitives setjmp() and longjmp().
When a script or multipart body parser exceeds configured memory limits, longjmp() immediately unwinds execution frames back to the top-level request handler. This non-local jump bypasses normal function return sequences and stack frame destructions. The attack surface centers on features that parse complex input payloads before user scripts run, specifically session.upload_progress and related multipart file handling functions.
The vulnerability class encompasses CWE-416 (Use After Free), CWE-755 (Improper Handling of Exceptional Conditions), and CWE-824 (Access of Uninitialized Pointer). Remote, unauthenticated attackers can leverage carefully crafted HTTP POST payloads to force out-of-memory conditions at exact execution points, destabilizing core execution structures.
The fundamental flaw resides in the execution gap between memory allocation tracking and pointer initialization during exceptional control flow jumps. When PHP processes HTTP requests containing session.upload_progress parameters, the runtime allocates dynamic session data structures to store progress metadata in memory.
If memory allocations fail during nested structure updates, the Zend Engine issues an emergency bail-out call (zend_bailout()), which internally triggers longjmp(). This immediately halts code execution within the active parsing loop and transfers control directly back to main() or php_request_shutdown().
Because longjmp() destroys stack frame context without executing cleanup logic or clearing partial pointers, references to incomplete data structures remain registered in global request contexts or heap tracking tables. When PHP subsequently executes shutdown destructors inside php_request_shutdown(), it attempts to traverse and release these partially initialized structures, causing access to uninitialized memory or use-after-free conditions.
During standard request handling, session uploading progress parameters are registered inside php_rinit_module() or request preprocessing routines. The control flow architecture relies on a execution landing pad initialized with zend_try macro wrappers.
// Conceptual representation of vulnerable parsing flow
PHP_MINIT_FUNCTION(session) {
// Upload progress initialization
if (PG(upload_progress_enabled)) {
zend_try {
// Allocation attempt for upload progress buffers
progress_data = ecalloc(1, sizeof(php_upload_progress_data));
// Memory exhaustion occurs here during deeply nested or bloated key parsing
populate_progress_keys(progress_data);
} zend_catch {
// zend_bailout() triggered via longjmp() jumps out of frame
// progress_data remains registered in memory tables with invalid pointers
} zend_end_try();
}
}When populate_progress_keys() calls engine allocators under memory pressure, zend_error_noreturn() invokes longjmp(). The control flow jumps directly to the request shutdown stage, skipping pointer completion.
During php_request_shutdown(), the runtime traverses request resources. It attempts to free progress_data members that were left containing uninitialized stack garbage or previous heap contents, enabling memory corruption and control flow hijacking.
Exploitation requires sender control over HTTP request headers and POST bodies sent to a web server running a vulnerable PHP interpreter. The attacker crafts a request using multipart/form-data encoding that activates the session.upload_progress feature.
By padding POST request bodies with high-density data payloads or repetitive structured keys, the attacker inflates memory usage up to the configured memory_limit threshold. The payload is calibrated so that memory exhaustion occurs precisely while session.upload_progress structures are being constructed.
Once longjmp() unwinds to request shutdown, heap spray techniques pre-arrange memory contents so that uninitialized pointer reads land on attacker-controlled memory. This permits the attacker to hijack function pointers inside Zend Engine request structures (such as stream destructors or custom resource handlers) to execute system commands in the worker process context.
Successful exploitation grants unauthenticated remote code execution (RCE) with the privileges of the underlying PHP-FPM or web server worker process (e.g., www-data or apache). An attacker can leverage this execution context to read local configuration files, extract environment variables, access local databases, or establish persistence.
The CVSS v3.1 base score is 9.8 (Critical), reflecting network accessibility without authentication or user interaction required. Under CVSS v4.0, the score is 9.2 (Critical), constrained primarily by attack precision requirements under tight timing conditions.
Because the vulnerability exists in core PHP engine components managing basic HTTP request processing, standard web applications utilizing PHP are vulnerable if session.upload_progress.enabled is active, regardless of the application framework in use.
The primary resolution is updating the PHP runtime environment to a non-vulnerable release branch. Patches have been published across supported PHP branches: 8.2.35, 8.3.36, 8.4.27, and 8.5.12.
For systems where immediate upgrades cannot be applied, disabling the session.upload_progress module provides effective operational mitigation. Modify php.ini as shown below:
; Disable session upload progress handling
session.upload_progress.enabled = OffAfter modifying php.ini, restart the main PHP service (e.g., systemctl restart php-fpm) to reload the runtime settings into worker processes. Web Application Firewalls (WAF) should also be configured to block abnormal multipart upload requests containing excessively repetitive or inflated key parameters.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H| Attribute | Detail |
|---|---|
| CWE ID | CWE-416 / CWE-824 |
| Attack Vector | Network (Unauthenticated) |
| CVSS v3.1 Score | 9.8 (Critical) |
| CVSS v4.0 Score | 9.2 (Critical) |
| EPSS Score | 0.05307 (92.56th percentile) |
| Impact | Remote Code Execution (RCE) |
| Exploit Status | Proof of Concept Available |
| CISA KEV Status | Not Listed |
A heap-based buffer overflow vulnerability in Pillow PyPI binary wheels (versions 11.1.0 to 12.x) allows remote code execution or application crash via crafted JPEG 2000 files processed by the bundled libopenjp2 library.
CVE-2026-109619 (PHP2Shell) is a critical Use-After-Free vulnerability in the core PHP engine caused by improper global state cleanup during out-of-memory exception handling across persistent worker requests.
In Python virtualenv prior to version 21.14.9, activation script generators and configuration writers use Path.exists() before writing files. Because Path.exists() resolves symbolic links, it returns False for dangling symlinks. Consequently, virtualenv skips unlinking pre-planted symbolic links or hard links, writing data directly to target locations outside the intended virtual environment directory.
A remote code execution vulnerability exists in Microsoft .NET due to untrusted data deserialization within the PresentationCore component. The flaw stems from implicit auto-conversion flags during clipboard data retrieval operations.
An out-of-bounds write vulnerability in Microsoft .NET Framework, .NET runtime, and Visual Studio allows unauthenticated remote attackers to execute arbitrary code via crafted pixel-shader bytecode or auto-converted clipboard payloads.
ASP.NET Core contains a thread deadlock vulnerability (CWE-833) that allows an unauthenticated remote attacker to cause a denial of service over the network by exhausting server thread pool resources.