PHP2Shell: our perimeter, third-party rescues and rebuilt hosting
After the two critical PHP vulnerabilities of 21 October 2026 we worked on three fronts: our own infrastructure, third-party servers whose owners asked us for help, and sites that had already been breached and needed rebuilding. Here is what we did, step by step.
Three fronts
On 20 October 2026 the PHP security team announced two critical vulnerabilities in the core of the language, later dubbed PHP2Shell. The patch was released the following day. From that moment we worked on three fronts.
The first is our own perimeter: the infrastructure that Cloudfactory's work runs on. The second is rescues for third parties: servers we do not manage, but that someone asked us to secure. The third is rebuilding other people's sites and hosting that had already been breached.
We name no names and give no details that would help an attacker. The method, however, can be reused: if you run a PHP server, you can follow the same steps.
What PHP2Shell is
PHP2Shell is the name given to two vulnerabilities, CVE-2026-109618 and CVE-2026-109619, both with a CVSS v4.0 score of 9.2. They allow remote code execution: whoever exploits them can run their own commands on the server, with no credentials needed (Fastly).
The flaw lies in how PHP handles out-of-memory errors and fatal errors. In certain cases memory is left in an invalid state and subsequent requests can use it. The issue affects PHP versions going back as far as 2004 (Laravel Forge).
| PHP branch | Fixed version |
|---|---|
| 8.5 | 8.5.12 |
| 8.4 | 8.4.27 |
| 8.3 | 8.3.36 |
| 8.2 | 8.2.35 |
| 8.1 and earlier | No official patch: end-of-life branches |
One detail matters a great deal for Laravel Forge users: Ubuntu's automatic updates do not touch PHP, which comes from a separate repository. The update has to be done by hand, server by server (Laravel Forge). Temporary mitigations and the versions to install are explained in our article of 22 October.
1. Our perimeter
Before helping others we put our own house in order. The first step was a read-only inventory, ready before 16:00 on 21 October, when the patch was due.
For each server we collected the operating system, the installed PHP versions, the version used by each site and the exposed services. Then we sorted everything by priority: first PHP 8.1 and earlier, with no patch; then 8.2, reaching end of life in December; finally 8.3, 8.4 and 8.5.
Where the system was supported we updated every installed PHP version, including unused ones. Then we restarted long-running processes and checked that every site was responding.
Where the system was end-of-life, no patch could arrive. There we reduced the attack surface:
- PHP hardening following CERT-EU guidance;
- web traffic accepted only from the Cloudflare network;
- SSH access restricted to management tools;
- database and cache reachable only from the server itself;
- Ubuntu Pro enabled for operating system patches.
We took the opportunity to carry out a full hardening: sites reachable only through Cloudflare, protection rules written directly into nginx, stronger isolation between sites, passwords and keys renewed. We removed every plugin that was not essential and, where possible, replaced them with proprietary code we developed ourselves. Fewer third-party components means fewer doors to watch.
The definitive solution is a new server, with a supported system, PHP 8.4 and MySQL 8.4. Sites move across one at a time, keeping the same IP address and without touching DNS.
2. Rescues for third parties
In the days after the vulnerability we were also asked for help with servers we do not manage. Often there was no contract in place. We secured them anyway, because leaving them exposed was too great a risk.
The typical case was a server left on an unsupported version of Ubuntu. The PHP repository no longer published updates for that system, so the patch could not arrive. We applied the same mitigations as in our own perimeter and separated the security groups, so that different servers no longer trusted one another.
During this work we found:
| What we found | What we did |
|---|---|
| Forgotten servers, still running and exposed | Disk snapshot and shutdown |
| Old installations left online after a migration | Reported to whoever could shut them down |
| Diagnostic and monitoring pages reachable from the Internet | Removed or closed |
| Files uploaded by users through forms, downloadable by anyone who knew the address | Direct access blocked |
| Mail server running an outdated version | Updated, with a check of the email flow |
On every server we ran a read-only check script. It looks for recent PHP files in upload folders, altered WordPress files, unknown administrators, unusual crashes and suspicious logins. The timeline is based on the files' status-change time (ctime), which an attacker cannot forge.
For each server we left the people in charge a clear summary: what we did, which risks remain open and what is needed to close them. No sensitive technical details, because these documents are often forwarded.
3. Rebuilding other people's sites and hosting
Some of the sites that came to us had already been breached, before and independently of PHP2Shell. In these cases updating is not enough: you have to rebuild.
The most complex case was a hosting environment attacked several times, starting from a vulnerable file-manager plugin. An earlier clean-up had been incomplete. Hidden backdoors were left behind, along with a malicious plugin disguised as a caching plugin, fake administrators and even an exception added to the SSH configuration.
Other sites had been hit by an automated tool that exploits a WordPress vulnerability from July 2026. It creates fake administrators and hunts for payment system credentials.
To rebuild we always followed the same steps:
- 01
Isolate and preserve the evidence
Site taken offline, processes stopped, access disabled, copy of the database and of the file list.
- 02
New server from scratch
Supported operating system, PHP 8.4, MySQL 8.4, ports open only to Cloudflare and management tools.
- 03
Clean sources only
WordPress, themes and plugins downloaded again from official sources. Custom code was reviewed by hand before going back in.
- 04
Data in quarantine
The database goes through a separate area and is cleaned before import.
- 05
User clean-up
In one case we removed more than 1,700 fake accounts, combining several criteria so as not to touch real customers.
- 06
All keys renewed
Passwords, WordPress keys, payment and email-sending credentials.
- 07
Email rebuilt
New credentials with minimal permissions and correct SPF, DKIM and DMARC records.
For a live e-commerce site the switchover uses a final export and an incremental import, so that no order is lost.
Hacked site or unsupported server?
If your site has been compromised, or the server it runs on no longer receives updates, we can help you understand what happened and start again from a clean base. Write to us and we will tell you where to begin.
How we wrote this article
At Cloudfactory we also use artificial intelligence in our editorial work: it helps us find and cross-check sources, compare data, set up the structure and polish the language. The system we use is configured by us, with instructions, examples and procedures built around the way we write. Our team checked every source, corrected the text and approved the published version. The assessments and choices are Cloudfactory's, and we are accountable for them.
Frequently asked questions
Is my WordPress site vulnerable to PHP2Shell?
It is if the server runs a PHP version earlier than the fixed ones: 8.5.12, 8.4.27, 8.3.36 or 8.2.35. The WordPress version is irrelevant: the problem is in the language.
Are the server's automatic updates enough?
Often not. On many servers PHP comes from a repository outside the operating system's own, which automatic updates do not touch.
I use PHP 8.1 or 7.4. What should I do?
Move to a supported version, at least 8.3. In the meantime, restrict access to the server and apply the mitigations recommended by CERT-EU.
Is updating PHP enough?
No. You need to restart the processes that use PHP and check that nobody got in before the patch.
Is a static or headless site exposed?
A static site served from a CDN does not execute PHP when visited, so it is far less exposed. The admin panel or APIs that feed it still need protecting.