Skip to content

PHP2Shell: How We Closed and Verified Two Critical PHP Vulnerabilities

Incidents & Status  ·   ·   ·  8 min Reading time

In brief
  • On 21 October 2026, the PHP project closed two critical vulnerabilities, CVE-2026-109618 and CVE-2026-109619, together called “PHP2Shell”. Both allow remote code execution and are rated CVSS 4.0 9.2.
  • That morning, hours before the patch, we switched off the feature through which the known attacks run. Shortly before the release, we took PHP offline entirely as a precaution.
  • Each system only went back online once it was demonstrably running the patched version. The Plesk panel stayed off until Plesk delivered its own update on the morning of 22 October.
  • We found no traces of attacks. We checked the claims that the update is not enough ourselves. None of them was confirmed.

A vulnerability in PHP does not affect one application, but almost all of them: WordPress, Nextcloud, shops, forums, webmailers. We reacted accordingly fast. This post describes what we did and when, and what we checked ourselves along the way.

What the vulnerabilities are

Both bugs sit in the core of PHP and concern the time between two requests. A PHP-FPM process handles many requests one after another. Between them, it has to clean up its state completely.

  • CVE-2026-109618 (RCE via OOM corruption): When PHP runs out of memory, it aborts the current request via a jump. In some places, this leaves memory in a half-finished state that the later cleanup still reads. According to the security advisory of the PHP project, this can be triggered deliberately and pushed all the way to code execution.
  • CVE-2026-109619 (RCE via stale global state): Global pointers briefly point into the memory of a request. If they are not reset cleanly, the next request reads memory that has already been freed. Here too, the advisory of the PHP project describes code execution as the consequence.

Diagram: Without the patch, a crafted request pushes the PHP process to the memory limit, remnants stay in memory, and the next request executes foreign code as a result. Patched, PHP cleans up the remnants completely and the next request gets a normal response.

Both are fixed in PHP 8.2.35, 8.3.36, 8.4.27 and 8.5.12 (PHP 8 changelog). The central fix is titled “Avoid state corruption via bailout”. The CVE entries: CVE-2026-109618 and CVE-2026-109619.

The timeline with times of day

On 20 October, the PHP project had announced that a security release for two critical vulnerabilities would be published the following day, scheduled for 16:00 German time. No details were available in advance. We used the time until then.

Time (CEST)What happened
21 Oct, from 07:30First protective measure: session.upload_progress switched off, first on our website, then step by step in web hosting, on Nextcloud and on the mail servers.
21 Oct, until 14:00Firewall rule against the known attack path in web hosting set up and tested. All updates that were already available applied.
21 Oct, 15:36PHP publishes the patched versions, earlier than announced.
21 Oct, 15:37We take PHP offline on our systems as a precaution. This had been planned for 15:45. Experience shows that mass scans begin immediately after a patch is published.
21 Oct, 16:03Our website is running again, with patched PHP.
21 Oct, 16:22–16:46Mail servers, web hosting, Nextcloud and most applications are back online, each only after the running version was checked.
21 Oct, around 17:45Nearly all remaining applications are back online after their images were rebuilt.
22 Oct, 01:56Plesk releases version 18.0.81.4 with a patched panel PHP.
22 Oct, 06:36After our own check, we switch the Plesk panel back on.

For most services, this meant an interruption of between half an hour and an hour. We accepted that deliberately: under our rule, no system goes back online without demonstrably patched PHP.

What we did

After the release, we updated all PHP installations under our responsibility: web hosting under Plesk and KeyHelp, the Nextcloud instances, the webmailers of the mail servers, our own website and internal applications. The older PHP versions 7.4, 8.0 and 8.1, which Plesk still ships, also received the corresponding updates.

An update alone was not enough for us. That is why three additional layers of protection apply:

  1. session.upload_progress is off everywhere and locked. The publicly described attack chains use this feature to write data into the session. We switched it off server-wide and locked it with php_admin_flag so that neither a .user.ini nor a domain setting can switch it back on.
  2. PHP processes are renewed regularly. With pm.max_requests = 500, every process terminates after 500 requests at the latest. State that lingers between requests therefore does not live indefinitely.
  3. The web application firewall blocks the attack path. Our own ModSecurity rules reject requests that send the field PHP_SESSION_UPLOAD_PROGRESS, including in a variant with an obfuscated Content-Type.

Diagram of the four protection layers: 1. The firewall blocks requests with PHP_SESSION_UPLOAD_PROGRESS, 2. upload_progress is off and locked, 3. patched PHP cleans up between requests, 4. PHP processes are renewed after 500 requests. An attack fails at layer 1, a bypass attempt at layer 2.

On top of that, there is monitoring that checks every ten minutes for PHP crashes, for shells started by a web PHP process, and for configurations that switch upload_progress back on.

Why the Plesk panel was offline

The Plesk administration interface does not run on the PHP of the websites, but on its own, built-in PHP version. On our side, that was PHP 8.4.25 on 21 October, so unpatched, with upload_progress switched on and reachable from outside. This PHP cannot be replaced by ourselves.

We therefore switched the panel off until Plesk delivers an update. That came with Plesk 18.0.81.4 on the morning of 22 October. Before switching it back on, we checked that the panel actually runs on PHP 8.4.27, and we additionally switched off upload_progress there as well. The websites themselves ran normally during this time; only logging in to the panel was not possible.

What we checked ourselves

As early as the evening of 21 October, claims were circulating on social networks and on GitHub that the update does not help or that bypasses already exist. We did not rely on any of them, but checked each one ourselves.

  • Running version instead of package list: An installed version says nothing about what a running process actually executes. We queried every PHP pool directly for the version it reports and whether upload_progress is off. In the process, we noticed, for example, that on one system the PHP of the websites was current but that of the command line was not.
  • The fix itself: We compared whether the published versions actually contain the central fix. The affected source files are patched identically in all four release branches.
  • Our own lab test: On a patched PHP 8.4.27 with upload_progress switched on, a file name chosen by the attacker ends up in the session file. With the feature switched off, no session file is created at all. Exactly this step is then missing from the known attack chains.

The unconfirmed claims

  • “Remaining chains” after the patch: Several public repositories show alleged attacks against patched PHP. We read the code. Each of these chains presupposes at least one of the following: upload_progress switched on, a still unpatched version such as 8.4.26, or an additional vulnerability in the application itself, such as insecure unserialize(). Against our configuration, none of them works.
  • A “follow-up” patch: A pull request in the PHP repository promised additional hardening against both vulnerabilities. It was closed the same evening and not merged. Another, older proposal on session handling is open, but plays no role when upload_progress is switched off.
  • Exploit archives: In some cases, “working” exploits were offered for download, unencrypted and of dubious origin. With vulnerabilities of this size, such archives often contain malware themselves. We did not download them and did not run any foreign exploit code on our servers.

Traces of attacks

We searched access, error and firewall logs for the known patterns. What we found were scans. On 21 October at 16:22, for example, a scanner that identified itself as a PHP2Shell scanner sent a crafted request to our web hosting. The firewall blocked it, and the PHP behind it was already patched at that point. We found no indications of successful exploitation.

What is still open

The new versions 8.4.27 and 8.5.12 bring a bug of their own: in certain cases, the SimpleXML extension can crash (GH-24488). A correction is in progress. The crash has not occurred on our side so far. Our monitoring watches for it, and we will apply the follow-up versions as soon as they are released.

What this means for you

Web hosting, Nextcloud and mail: You don’t need to do anything. The updates and the hardening have been applied. One exception: if your application uses an upload progress bar via session.upload_progress, it now shows no progress. The upload itself still works.

Your own vServer or root server: Here you are responsible yourself. Check the running PHP-FPM service, not just php -v on the command line. At least 8.2.35, 8.3.36, 8.4.27 or 8.5.12 is required. Then restart PHP-FPM and set session.upload_progress.enabled = Off. Anyone running Plesk or another panel with its own PHP additionally needs the panel vendor’s update.

We are happy to answer questions about your server through our ticket system.

Frequently asked questions

What is PHP2Shell?
PHP2Shell is the name for two critical vulnerabilities in PHP, CVE-2026-109618 and CVE-2026-109619. Both arise because PHP does not fully clean up its state between two requests. An attacker can exploit this to execute code remotely. Both are rated CVSS 4.0 9.2.
Which PHP versions close the vulnerabilities?
PHP 8.2.35, 8.3.36, 8.4.27 and 8.5.12, all released on 21 October 2026. What matters is the version reported by the running PHP-FPM service. After the update, the service must be restarted.
Do I need to do anything as a web hosting customer?
No. We have updated all PHP versions in web hosting and additionally switched off session.upload_progress. Only an upload progress bar that relies on this feature no longer shows any progress. The upload itself still works.
Why was the Plesk panel temporarily unreachable?
The Plesk interface runs on its own PHP version, which only Plesk can update. It was still unpatched. We therefore switched the panel off until Plesk delivered an update on the morning of 22 October. The websites ran normally during this time; only logging in to the panel was not possible.
Were any systems attacked?
We found no indications of successful exploitation. Scans showed up in the logs. The firewall blocked them, and the PHP behind it had already been updated at that point.
Is it true that the update is not enough?
We checked the widespread claims ourselves. Every alleged bypass presupposed session.upload_progress switched on, an unpatched PHP version, or an additional vulnerability in the application. With current PHP and upload_progress switched off, none of them works.
Prepaid-Host.com is itself a provider of servers, web hosting and domains, and reports here on its own market. How we handle that is set out in our disclosure statement.