Milind Daraniya

CVE-2026-109618 and CVE-2026-109619 Explained: How PHP2Shell Works

Published October 23rd, 2036 9 min read

When a security announcement mentions remote code execution, memory corruption, and critical severity, the first questions developers usually ask are: What is actually broken? Does it affect my application? And what should I change?

PHP2Shell involves two related weaknesses in PHP's handling of requests and internal memory.

Both vulnerabilities were assigned CVSS 4.0 scores of 9.2. They can potentially allow unauthenticated remote code execution on affected systems, but their underlying failure paths are different.

Understanding that distinction helps explain why an ordinary application-level fix cannot address the entire problem.

1. CVE-2026-109618: Out-of-memory corruption

PHP applications process different types of incoming data, including URL parameters, request bodies, form submissions, and file uploads.

Processing that information requires memory.

PHP also supports memory limits, which help prevent an individual script from consuming an excessive amount of memory. When a request encounters an allocation failure, the runtime needs to terminate or recover from the failure without leaving its internal state inconsistent.

The problem described by CVE-2026-109618 occurs when an out-of-memory condition interrupts processing while internal request data is only partially initialized.

Subsequent cleanup can then operate on invalid or uninitialized data. Under the conditions described in the advisory, this memory corruption can potentially be exploited to achieve remote code execution.

This is not simply a situation where a PHP page displays an out-of-memory error. The concern is what happens to the runtime's internal state when that failure occurs.

A simplified example

Imagine an application that processes uploaded documents.

A simplified request flow might be:

1. The browser submits a request.
2. The web server forwards the request to PHP.
3. PHP processes the incoming request data.
4. A memory allocation failure interrupts processing.
5. PHP must clean up the partially processed request.

In normal operation, the runtime should handle this failure safely.

The vulnerability concerns a failure path in which partially initialized internal data can later be treated as valid.

This example illustrates the general concept. It is not an exploit demonstration, and an ordinary file upload does not automatically indicate that a server is vulnerable.

The underlying issue is in PHP's internal request handling rather than a particular file-upload controller.

2. CVE-2026-109619: Stale global state

The second vulnerability involves a different memory-management problem.

During request processing, PHP maintains internal state that may refer to memory allocated for the current request.

That memory has a lifecycle. Once it is freed, code should no longer use the old reference as though the memory were still valid.

CVE-2026-109619 concerns a situation in which internal global state can retain a reference to request memory after that memory has been freed. A subsequent request handled by the same worker may encounter the stale state before it has been properly initialized.

This is related to a class of memory-safety problems commonly described as use-after-free.

Depending on the conditions, the vulnerability can lead to memory disclosure or remote code execution.

Why can request cleanup matter?

PHP workers can handle multiple requests during their lifetime.

A simplified example illustrates the concern:

Request A
    |
    v
PHP creates request-specific state
    |
    v
The request ends and its memory is released
    |
    v
An internal reference unexpectedly remains
    |
    v
Request B reaches the worker
    |
    v
The stale reference is encountered

This is a conceptual illustration of the lifecycle problem, not a guaranteed sequence for every request or an exploit procedure.

The central principle is that releasing memory is not enough if references to that memory can remain accessible and later be used incorrectly.

3. What is the difference between the two vulnerabilities?

Although both vulnerabilities involve PHP internals and can lead to remote code execution, the underlying problems differ.

DetailCVE-2026-109618CVE-2026-109619
Main issueOut-of-memory handling and corrupted internal stateStale global state referencing freed memory
Failure pathPartially initialized data is mishandled during cleanupOld request state can be encountered after its memory is freed
Potential consequenceMemory corruption and remote code executionUse-after-free, potential memory disclosure, and remote code execution
Required responseInstall the applicable PHP security fixInstall the applicable PHP security fix

Both vulnerabilities affect the runtime, so the same fundamental remediation applies: install a verified fixed PHP release or a vendor package containing the relevant patches.

The official PHP advisory contains the detailed technical descriptions and temporary mitigation guidance.

4. Why Laravel middleware cannot fully protect against this issue

Consider a normal Laravel request:

Route::post('/documents', [DocumentController::class, 'store']);

A developer might add request validation:

$request->validate([
    'title' => ['required', 'string', 'max:150'],
    'document' => ['required', 'file', 'max:5120'],
]);

This is useful application-level protection. It can reject invalid input and enforce business requirements once the application processes the request.

However, PHP must begin handling the request before Laravel can run the controller's validation.

This means the validation code does not repair the runtime vulnerability.

The same principle applies to authentication middleware, CSRF protection, prepared SQL statements, and updates to Composer packages. These controls solve different classes of problems.

We should continue using them, but we must not confuse application security with runtime patching.

5. Does increasing the PHP memory limit solve CVE-2026-109618?

Not completely.

It is tempting to assume that raising the memory limit will eliminate the risk because one vulnerability involves out-of-memory handling.

However, the official advisory explains that preventing the configurable PHP memory-limit failure does not eliminate every possible allocation failure that could reach the vulnerable path.

Increasing memory limits indiscriminately also carries a practical operational risk: resource-intensive requests can consume more server memory.

Any temporary configuration change should therefore be reviewed against application requirements and server capacity.

The proper long-term response is to install a fixed version of PHP. Temporary mitigations, where appropriate, only reduce exposure to particular attack paths.

6. Which versions should developers install?

The PHP security release published on October 21, 2026, identifies these fixed releases:

PHP 8.5.12
PHP 8.4.27
PHP 8.3.36
PHP 8.2.35

Install the applicable fixed version on the branch you use.

If your operating system manages PHP packages, consult its security advisory as well. Distribution maintainers sometimes backport security patches to packages whose version numbers do not exactly match upstream PHP releases.

For PHP 8.1 and older, check whether your vendor provides a security-maintained package with the fix and plan a migration to a supported PHP branch.

Do not assume that a runtime is patched simply because the application continues to work after a normal deployment. Verify the installed package and active runtime.

7. A practical example of checking a Laravel server

On a Linux server, begin by checking the command-line runtime:

php -v

Identify the PHP configuration:

php --ini

Then inspect the installed packages on a Debian- or Ubuntu-based server:

dpkg-query -W 'php*' 2>/dev/null

If multiple PHP versions are installed, identify which PHP-FPM pool or Apache configuration serves the application.

For example, a server can have PHP 8.2 installed for one application and PHP 8.1 installed for another. Checking only php -v may therefore provide an incomplete picture.

Once the applicable security update is installed, restart the appropriate PHP workers or web server and verify the application again.

Avoid making server configuration changes blindly on a production system. Confirm the active PHP version, package source, and service names before applying an update.

Conclusion

PHP2Shell demonstrates why low-level runtime vulnerabilities deserve immediate attention, even when application code follows established security practices.

CVE-2026-109618 involves out-of-memory handling and corrupted internal state. CVE-2026-109619 involves stale references to memory that has already been freed.

These are different failure mechanisms, but the defensive priority is the same: update PHP, verify the runtime used by every web-facing application, and investigate potential compromise where exposure or suspicious activity exists.

The key takeaway for developers is simple: validating incoming data is necessary, but it cannot replace fixing a vulnerability in the runtime that processes that data.