DEV Community

Cover image for PHP2Shell Explained: How Two Memory-Handling Bugs Can Lead to Remote Code Execution
Harsh Mangalam
Harsh Mangalam

Posted on

PHP2Shell Explained: How Two Memory-Handling Bugs Can Lead to Remote Code Execution

On October 21, 2026, the PHP project disclosed two critical security vulnerabilities affecting PHP's core runtime.

The vulnerabilities, tracked as CVE-2026-109618 and CVE-2026-109619, received a CVSS v4.0 severity score of 9.2 out of 10.

They are collectively known as PHP2Shell.

What makes this incident particularly interesting for developers is that these are not ordinary application-level bugs. They involve PHP's internal memory management and error-handling paths, and successful exploitation can potentially lead to remote code execution without authentication.

In this article, we'll explore what the vulnerabilities are, how the underlying programming concepts work, and why a bug in a language runtime can affect applications across the web.

1. What is PHP2Shell?

PHP is a server-side programming language used by millions of websites and applications, including WordPress, Drupal and many custom web services.

When a browser sends an HTTP request to a PHP application, the PHP runtime processes that request, executes the relevant application code and returns a response.

A simplified request lifecycle looks like this:

Incoming HTTP request
        |
        v
Web server / PHP runtime
        |
        v
Request initialization
        |
        v
Application code executes
        |
        v
Response returned
        |
        v
Request cleanup
Enter fullscreen mode Exit fullscreen mode

PHP2Shell affects the internal request-processing lifecycle.

The two vulnerabilities involve different failure scenarios:

  • CVE-2026-109618: An out-of-memory condition can interrupt request processing while internal request data is only partially initialized.
  • CVE-2026-109619: Internal request-related state can remain accessible after the memory backing it has been freed.

Under the right conditions, these flaws can lead to memory corruption and remote code execution.

An important detail is that the vulnerable processing can happen before the application's own PHP code runs. Consequently, an application-level login check cannot necessarily protect against these attack paths.

2. CVE-2026-109618: Remote Code Execution Through Out-of-Memory Handling

Let's start with the first vulnerability.

What is an out-of-memory condition?

Programs allocate memory to store data while they execute. PHP does this when processing request parameters, uploaded files and other input.

PHP also enforces memory limits to prevent scripts from consuming unlimited resources.

Consider this simplified example:

$data = str_repeat('A', 1024 * 1024 * 100);
Enter fullscreen mode Exit fullscreen mode

This attempts to create a string of approximately 100 MB.

If the process cannot allocate the required memory, the operation may fail.

A memory-allocation failure is not inherently a security vulnerability. Well-written software should handle such failures safely.

The problem arises when the program enters an unexpected execution path and its internal state is no longer consistent.

Where does longjmp() fit in?

PHP is implemented primarily in C. C provides a mechanism called setjmp() and longjmp() that can save and restore execution contexts.

In simplified terms, longjmp() allows execution to jump back to an earlier saved point rather than returning normally through every intervening function.

This can be useful for handling certain fatal errors, but it also makes control flow more complicated.

Imagine a request being processed like this:

Request initialization begins
        |
        v
PHP allocates internal request data
        |
        v
Memory allocation fails
        |
        v
Error handling interrupts normal execution
        |
        v
Control jumps to an earlier execution point
        |
        v
Request cleanup begins
Enter fullscreen mode Exit fullscreen mode

The critical question is: Was every piece of internal state initialized before cleanup began?

According to the PHP advisory, the out-of-memory handling involved in CVE-2026-109618 can interrupt execution while internal request data is only partially initialized.

Cleanup can then treat invalid or uninitialized data as if it were valid.

This creates a memory-safety problem.

Why can this become remote code execution?

Memory corruption can have different consequences, depending on what memory is affected and how the program subsequently uses it.

In some cases, it causes a crash. In others, carefully controlled corruption can influence program execution.

Security researchers reported that this vulnerability can be exploited to achieve remote code execution under relevant conditions.

The important distinction is that the issue is not simply that PHP runs out of memory. The security flaw is in how PHP handles the failure and subsequently processes its internal state.

3. CVE-2026-109619: The Danger of Stale Memory

The second vulnerability involves another classic memory-safety issue: using state after its backing memory has been freed.

This is closely related to a concept known as use-after-free.

What is use-after-free?

Imagine that a program allocates memory for an object:

char *buffer = malloc(128);
Enter fullscreen mode Exit fullscreen mode

The program uses the buffer and eventually releases it:

free(buffer);
Enter fullscreen mode Exit fullscreen mode

Once memory has been freed, the program must not continue treating the old pointer as a valid reference to that allocation.

For example:

free(buffer);

/* Unsafe: buffer no longer points to a valid allocation */
printf("%s", buffer);
Enter fullscreen mode Exit fullscreen mode

This is a simplified illustration of unsafe memory access, not an exploit for PHP2Shell.

The memory may be reused for something else. Reading or writing through the old pointer can therefore produce unpredictable behaviour, memory corruption or potentially exploitable conditions.

How does this relate to PHP2Shell?

PHP maintains internal state while processing requests.

According to the PHP advisory, CVE-2026-109619 involves request-owned internal state surviving after the memory backing it has been freed.

A later request handled by the same worker can encounter that stale state before normal initialization resets it.

The simplified lifecycle is:

Request A begins
      |
      v
Internal state references allocated memory
      |
      v
Memory is released
      |
      v
A stale reference remains
      |
      v
Request B reaches the same worker
      |
      v
Stale state is used before initialization
      |
      v
Potential memory corruption
Enter fullscreen mode Exit fullscreen mode

The actual execution paths are more complex than this diagram, but it illustrates the underlying problem.

The key issue is not simply that memory was freed. It is that internal state remained capable of referring to memory whose lifetime had ended.

Under the relevant conditions, researchers reported that this flaw can also lead to remote code execution.

4. Why Is This More Serious Than a Typical Website Bug?

Most developers think about security at the application layer.

For example, an application might check whether a user is authenticated before allowing access to a page:

if (!isAuthenticated()) {
    http_response_code(401);
    exit;
}
Enter fullscreen mode Exit fullscreen mode

This is a useful application-level control.

However, application code cannot protect against every vulnerability in the software executing it.

A vulnerable runtime may process an HTTP request before the request reaches the application's authentication logic.

The distinction looks like this:

Normal application attack

HTTP request
     |
     v
Application authentication
     |
     v
Application logic
Enter fullscreen mode Exit fullscreen mode

Compare that with a vulnerable runtime path:

Potential PHP2Shell attack path

HTTP request
     |
     v
PHP internal request processing
     |
     v
Memory-handling vulnerability
     |
     v
Potential code execution
     |
     v
Application code may never run
Enter fullscreen mode Exit fullscreen mode

This is why fixing an application's login logic, validating its form fields or updating a WordPress plugin does not, by itself, fix a vulnerability in the underlying PHP runtime.

PHP's security advisory identifies web-serving PHP installations as potentially affected, including PHP-FPM, Apache with mod_php, php-cgi, FrankenPHP and LiteSpeed. The exact exposure and exploitability depend on the deployment and vulnerability path.

5. What Could an Attacker Achieve?

Remote code execution means an attacker may be able to make a vulnerable process execute commands or code they control.

The consequences depend on the permissions and environment in which PHP runs.

Potential impacts include:

  • Access to sensitive files available to the PHP process.
  • Exposure of application configuration and database credentials.
  • Modification of website content or application files.
  • Execution of additional malicious programs.
  • Further compromise of systems accessible from the affected server.

Successful exploitation does not automatically give an attacker unrestricted control of the entire machine. Operating-system permissions, container isolation and other controls still matter.

Nevertheless, remote code execution in a web-facing runtime is a serious security issue because it can undermine the security boundaries of the application running on top of it.

6. Which PHP Versions Are Affected?

The PHP project released security updates on October 21, 2026.

The fixed releases are:

PHP branch Fixed version
PHP 8.5 8.5.12
PHP 8.4 8.4.27
PHP 8.3 8.3.36
PHP 8.2 8.2.35

The vulnerabilities affect older PHP versions as well. PHP 8.1 and earlier are no longer supported by the upstream project, although some operating-system vendors may provide backported security fixes.

If you manage PHP infrastructure, check your distribution's advisory as well as the version number. A vendor may backport a patch without changing the version string to match an upstream fixed release.

Updating the PHP package is not enough if old worker processes continue running. The affected services must load the patched runtime.

7. What Should Developers and Security Teams Understand?

There are three important lessons from PHP2Shell.

First, error-handling paths deserve the same security scrutiny as normal execution paths.

An allocation failure may seem like an availability problem, but incorrect cleanup or inconsistent state can turn it into a memory-safety vulnerability.

Second, memory lifetime is a security boundary.

A pointer that once referenced valid memory does not remain safe to use after that memory is released. Systems programming languages require developers to reason carefully about allocation, ownership and cleanup.

Third, application security depends on the entire software stack.

Secure application code is important, but it runs on top of a runtime, operating system, web server and supporting libraries. Vulnerabilities at any of those layers can undermine protections implemented elsewhere.

8. Further Reading

For the original technical details and remediation guidance, consult these sources:

Top comments (0)