Responding to a PHP zero-day across a managed WordPress fleet.
On 21 October 2026, two critical PHP flaws were announced with a leaked exploit and a same-day patch. In one working day we hardened our own servers, found and cleaned a client shop that had been hacked for 18 days, and moved 14 sites off unsupported PHP 7.4.
Client and site names are withheld. Sites are described by type only.
At a glance
| Sites moved from PHP 7.4 to 8.3 | 14 |
|---|---|
| Sites scanned for break-ins | 55+ |
| Compromised sites found and contained | 2 |
| Sites brought under continuous monitoring | 9 |
| Downtime caused by the work | Minutes |
| Product features shipped in response | 7 |
The trigger
PHP's security team pre-announced CVE-2026-109618 and CVE-2026-109619: two remote code execution flaws in PHP itself, rated 9.2. Details and an exploit tool had already leaked, and the patch was due at 14:00 UTC the same day.
- No login needed. Researchers showed the exploit working on default WordPress, WooCommerce, Laravel and Drupal installs.
- Firewalls can't stop it. PHP is hit before WordPress or any security plugin runs.
- Old PHP never gets the fix. Only PHP 8.2 and newer are patched. Anything on 7.4 stays exposed for good.
Some sites in our fleet ran PHP 7.4, both on our own server and on a partner host. The real job was to find every one of them and move it, safely, that day.
Hour one: securing our own infrastructure
Within the first hour our server ran only supported PHP versions, and nothing that didn't need to run.
- Inventory. We mapped the PHP version of every site on our infrastructure.
- Interim hardening. We switched off the PHP feature the early analysis pointed at. WordPress doesn't use it, so nothing broke.
- Smaller attack surface. Every PHP version no site needed was stopped and disabled.
- Unsupported sites upgraded. Every site still on PHP 7.4 was moved to 8.3 and checked.
- Certificate trust refreshed. Keys for several intermediate certificate authorities leaked the same day. We updated our trusted roots and confirmed none of our certificates were affected.
- A full break-in check. We reviewed accounts, access keys, logins, scheduled jobs, running processes and every WordPress install. No compromise was found.
The discovery: a shop hacked for 18 days
While planning the upgrade of a client's WooCommerce shop on PHP 7.4, our first read-only check found two database tools planted inside WordPress's own admin folder. The PHP flaw was not to blame: the site had been open since 3 October.
WordPress's own checksum check flagged files that "should not exist". The host's access logs, supplied later that day, filled in the rest:
| Date | What happened |
|---|---|
| 3 Oct | The attacker signed in with a real admin password through the shop's My Account form, which bypasses the hidden admin login, used a file-manager plugin to plant a web shell, and viewed orders. |
| 16 Oct | The attacker checked the backdoors still worked, signed in and viewed the orders page. |
| 19 Oct | The attacker signed in again and planted two database admin tools, one of them holding the database password. |
| 21 Oct | We found the intrusion and contained it the same day. |
Three weaknesses made it possible: the shop's login form bypassed the hidden admin page, a file-manager plugin turned one stolen password into full file access, and nothing alerted anyone for 18 days.
Containment
The shop was contained the same day without being taken offline.
- Backdoors quarantined, not deleted. Every planted file was moved outside the website and fingerprinted as evidence.
- Database and files verified. No hidden admin accounts or injected scripts; core and plugin files matched their official copies.
- Every session ended. New WordPress security keys signed everyone out, including the attacker.
- Credentials rotated. Administrator passwords and the database password were changed, and we confirmed the old database password was rejected.
- Attacker blocked at the host's server and in the site's firewall.
- Client informed of what had been accessed, so they could meet their data-protection obligations.
Safe upgrades: test first, then go live
Every live upgrade was rehearsed on a private copy first. Only sites where nothing broke went ahead.
The copy ran on our own server, unreachable from the internet, with customer emails and passwords scrubbed. It applied the updates on PHP 7.4, switched to 8.3, and loaded the key pages and admin screens after each step. The tests caught what a blind switch would have hit:
- A shop that would have gone fully offline. An abandoned SEO plugin, pulled from wordpress.org over a security issue, crashed every page on PHP 8. It had to be switched off before the change.
- Amazon affiliate code in two sites' plugins that loads fine at first, then crashes on the next product refresh.
- An email-validation plugin that crashes on a public request.
- Plugin order. Contact Form 7's latest release only runs on PHP 8.3, so it is updated after the switch, never before.
The live runs then followed the tested order: backup, updates on 7.4, switch to 8.3, held-back updates, Cyber Securitise installed and connected to the dashboard, with a page check after every step.
Fleet sweep
We checked every other site on the partner host the same day. None showed signs of the shop's attacker, but six had the same open door and one carried an older hack.
| Finding | Sites | Action |
|---|---|---|
| File-manager plugin active (the tool used on the shop) | 6 | Removed |
| Dormant compromise from 2019 (fake admin accounts, hidden backdoor files) | 1 | Contained |
| Plugins withdrawn from wordpress.org, two of them over security issues | 9 | Flagged for replacement |
| Inactive add-on with a hidden login link | 1 | Kept switched off |
| Core files damaged by an outdated site-setup process | 16 | Repaired; process fixed |
Automated bots probed nearly every site throughout the day. Every attempt was refused, and their addresses are now blocked across the fleet.
What we built the same day
By evening, everything we had done by hand on the shop was a product feature, released to every site in Cyber Securitise 1.23.
- Planted-file detection. Any PHP file in WordPress's own folders that WordPress doesn't ship is flagged as high risk and can be quarantined in one click. It would have caught every backdoor on the shop on day one.
- Withdrawn-plugin warnings. Plugins pulled from wordpress.org are flagged, and owners are emailed about those pulled over security issues.
- PHP runtime warnings. Unsupported PHP versions are flagged as high risk.
- Break-in timeline. The incident page shows what was planted, when, from which address and the likely way in, with a one-click block.
- Leaked-password warning. If a planted file contains the database password, the owner is told to change it at the host.
- Emergency push. Staff can send a protective setting to every site at once, with automatic undo if a site breaks.
- Upgrade test lab. The test-copy method above, built into the dashboard: one click copies a site, upgrades it privately and reports what breaks.
Lessons learned
A day like this tests process as much as tools. These are the changes we made to how we work.
| Lesson | What we changed |
|---|---|
| A test copy only proves the pages it opens | Upgrade tests now open every page that uses a plugin feature, not a fixed sample. |
| Hosting tools can change only part of a credential | Every credential change is verified by confirming the old one is rejected. |
| A safety check that stops a release earns its place | Our staged rollout halted a faulty update on its first site. Every release now checks it carries all earlier fixes. |
| An interim setting is not a fix | We call workarounds hardening, and treat the vendor patch as the only fix. |
Where things stand
Every remaining site on unsupported PHP has been tested and has a scheduled upgrade, and our own servers take the PHP patch as soon as it is released. The wider lesson: rehearse every change on a copy, and treat anything short of the vendor patch as buying time, not protection.