EN
Agency
← All articles
Security 22 Oct 2026 6 min read by Les Techniciens du Net

PHP2Shell: the two critical PHP flaws of 21 October 2026, explained

Two flaws in the PHP engine itself (CVE-2026-109618 and CVE-2026-109619, rated 9.2/10) let an attacker take over a server without an account. The technical mechanism, the fixed versions and what to do right now.

#php#security#cve#wordpress

On 21 October 2026, the PHP team shipped four emergency releases: 8.5.12, 8.4.27, 8.3.36 and 8.2.35. They fix two flaws in the engine itself, nicknamed PHP2Shell and rated 9.2 out of 10 (CVSS v4). They let an attacker with no account run code on the server with the web process’s privileges, sometimes before the site’s own code even runs.

The flaw is not in WordPress or in a plugin: it is in PHP. Every site running PHP is affected, whatever software it uses (WordPress, Drupal, Joomla, PrestaShop, custom code).

CVE-2026-109618CVE-2026-109619
NatureMemory corruption when PHP runs out of memoryMemory reused after being freed, from one request to the next
TriggerA crafted form (multipart) requestA fatal error or timeout that interrupts cleanup
Confirmed takeoverApache with mod_php, default settingsmod_php, and PHP-FPM through upload progress tracking

CVE-2026-109618: memory running out at the wrong moment

PHP caps the memory of each request (memory_limit, 128 MB by default). When an allocation goes over that limit, PHP raises a fatal error and leaves the current function with longjmp(): a jump that abandons the work wherever it stands, without finishing it.

The problem is the order of operations. In some places, PHP marks data as ready before it has finished allocating it. Datadog’s analysis gives an example: when adding an entry to a hash table, the structure that holds $_POST, PHP first increments the element counter, then allocates the key. If that allocation fails, the table counts a slot whose content is whatever was left in memory.

At the end of the request, PHP destroys $_POST and walks every counted slot. It therefore reads those bytes as PHP values. If the attacker managed to place chosen bytes there, cleanup runs their code.

Three steps: a multipart request pushes PHP past its memory limit, PHP abandons the insertion of a $_POST entry halfway, then end-of-request cleanup reads that entry and runs the attacker's code

Running out of memory is not the goal: it is the way to leave a half-built structure behind.

The attacker still has to run out of memory without exceeding PHP’s size limits. The official advisory describes how a multipart request (a form with file uploads) achieves it:

  • with no usable declared length, the request passes the initial post_max_size check;
  • each part can carry an unlimited number of headers, which cost far more memory inside PHP than on the wire;
  • empty file fields do not count towards max_file_uploads, yet still create metadata arrays;
  • nested names (a[b][c]…) multiply that work.

Why mod_php is the most exposed. With Apache and mod_php, PHP reads the request body as soon as it starts, and still runs end-of-request cleanup when that startup fails. The attack therefore succeeds before any application code, with default limits. PHP-FPM stops the process when startup fails: no complete attack has been demonstrated, but the flaw remains reachable if the application itself causes an out-of-memory condition later on.

CVE-2026-109619: a pointer forgotten from one request to the next

A PHP process (a “worker”) serves many requests in a row. Some of the process’s global variables point to memory that belongs to the current request. At the end of the request that memory is freed; if the variable is not reset, the next request reads an area that has already been released and possibly reused. This is a use-after-free.

It happens when a fatal error or a timeout interrupts the reset. Two paths are confirmed:

PathSetting involvedWhere the attack is confirmed
File upload progress trackingsession.upload_progress.enabled, on by defaultmod_php and PHP-FPM
Fatal error backtracesfatal_error_backtraces (PHP 8.5)mod_php

The attacker’s requests must land on the same worker. A server with many workers takes more attempts: that is not a protection.

What the fix changes

  • No more longjmp() on out-of-memory. A “soft” limit reports the error at the next safe point of execution; a higher “hard” limit stops the process immediately, with no risky cleanup.
  • State that outlives a request (error backtraces, session, error state, OPcache) is reset at the end of every request.

Who is affected, and which version to install

BranchFixed version
PHP 8.58.5.12
PHP 8.48.4.27
PHP 8.38.3.36
PHP 8.28.2.35
PHP 8.1, 8.0, 7.4no new release: minimal fixes published as source code, for distributions

Every runtime that serves pages is in scope: Apache with mod_php, PHP-FPM, php-cgi, FrankenPHP, LiteSpeed. Red Hat rates the risk somewhat lower, because the attack requires a very precise out-of-memory condition. A working exploit was built during the research, the information leaked a day before publication, and researchers report exploitation attempts. Beware of fake exploit code published on GitHub as well: do not run it.

What to do now

  1. Update to the fixed version of your branch, then restart every PHP process (Apache, PHP-FPM) and rebuild Docker images. This is the only complete protection.

  2. Check the version the site actually uses, not the command-line one, which can differ. On shared hosting the version is chosen in the host’s control panel: make sure it carries the fixed number.

  3. If the update has to wait, set these in php.ini or the pool configuration, then restart the processes (ini_set() and .user.ini come too late):

    • session.upload_progress.enabled = 0;
    • fatal_error_backtraces = 0 on PHP 8.5;
    • memory_limit = -1, enforced by the administrator, together with a request size limit at the web server or proxy: without it, the server is no longer protected against memory exhaustion;
    • block multipart requests at the proxy if the site accepts no file uploads.

    These measures are partial: they close the known paths, not the cause.

  4. Monitor: memory exhaustion errors at the very start of a request (“Allowed memory size exhausted”, “Unknown on line 0”), form submissions with huge field names (several megabytes), crashing PHP processes, and above all a web process spawning a shell. A successful attack can return a normal response (status 200) without crashing anything.

What about sites without PHP?

A static site, or an application written in Node.js or Python, is not affected by these two flaws: they live in the PHP engine. Every platform has its own. What really protects you is a version still maintained by its developers, and updates applied within days of their release.

Sources: official PHP security advisory (GHSA-w8hw-w9fx-j79w), Rapid7, Datadog Security Labs, JFrog and Red Hat, accessed 22 October 2026.

Drag to move around, pinch to zoom.