← All posts

PHP2Shell: how we patched our clients' servers in two days

When PHP disclosed two critical remote-code-execution flaws, we patched more than 20 client websites and systems across three servers — including ones stuck on end-of-life PHP — with a tested fallback for every change.

20+client websites and systems patched
2 daysfrom the advisory to patched
3servers hardened at the same time

On 21 October 2026 the PHP project released fixes for two critical vulnerabilities, CVE-2026-109618 and CVE-2026-109619, quickly nicknamed PHP2Shell. Both allow an attacker to run code on a server without logging in, and both affect any PHP installation serving web requests — which covers almost every WordPress site and most PHP business systems. Government security agencies, including CISA and the UK's NCSC, told everyone to patch immediately, and exploitation attempts had already been seen.

Several of our clients run on PHP. This is what we did, what went wrong along the way, and what is still on the list.

What we were looking after

Three servers hosting a mix of client work:

  • Marketing and e-commerce sites on WordPress
  • Laravel applications with background queues and schedulers
  • A repair management system used across several retail brands
  • Older systems still running on PHP 7.4 — and two on PHP 5.6

Most of these could be upgraded within the same PHP branch. The older ones could not, and they needed a different plan.

Day one: patch everything that can be patched

For every site and service we followed the same routine:

  1. Back up first — website files, a fresh database export and the exact container settings.
  2. Upgrade within the same branch (8.2 → 8.2.35, 8.3 → 8.3.36, 8.4 → 8.4.27) so nothing else changed at the same time. We pinned official images by digest, so a rebuild can't silently pull something different.
  3. Check the version that actually serves requests, not just the command-line version. These can differ, and the web-facing one is the one that matters.
  4. Verify the home page, login, API endpoints and error logs before moving on.

The first seven WordPress sites were patched and verified the day after the advisory.

End-of-life PHP has no update button

PHP 7.4 and 5.6 stopped receiving official updates years ago, so "just upgrade" wasn't available for those systems.

  • PHP 7.4: the PHP project published a security patch for these two flaws on older branches. We built PHP 7.4 from source with that official patch applied, kept every extension and setting the same, and ran PHP's own regression tests against both the FPM and Apache builds. Where a trusted package vendor had already shipped the same backport, we used theirs instead.
  • PHP 5.6: no patch exists. Where the client confirmed a site was no longer needed, we took it offline cleanly — it returns a maintenance response, and all files and data are kept. Where a system was still in use, we kept it behind an authentication layer and wrote up a step-by-step plan to migrate it to a supported PHP version.

A backported patch fixes these two vulnerabilities. It doesn't make old PHP safe in general, and we said so in every report.

A fallback for every change

Emergency work is where mistakes happen, so we planned for them.

  • Every service got a rollback — the previous image and a one-line script to switch back. Rollbacks only change routing and code, never the database, so no new orders or form entries are lost.
  • Risky changes were tested on isolated copies first, with outgoing email and payments blocked so tests couldn't reach real customers.
  • Automatic checks triggered rollbacks, and they did their job twice. One site briefly lost its database connection because a newer deployment tool read a $ in an existing password as a variable. Another switch was rolled back automatically when page content didn't match the old site. Both were fixed and re-verified before going live.

While we were in there

Patching closed the immediate hole. We also fixed the things that would make the next one worse:

  • Blocked public access to old backup files, debug logs and configuration files that had been left in web folders.
  • Locked down server access — SSH keys only, through a single jump host, with a firewall and automatic blocking of repeated login attempts.
  • Isolated websites from each other — each site's container now has a read-only file system, no ability to gain extra privileges, and its own network. If one site is compromised, it can't reach the others or the admin tools.
  • Upgraded an old MySQL 5.7 database to MySQL 8.4 LTS, step by step through the supported upgrade path, with row counts checked before reopening the site.
  • Moved one legacy WordPress site from PHP 7.4 to PHP 8.3, fixing 19 files that weren't compatible with PHP 8.

What we found

On one site that was no longer in use, we found a backdoor that had been planted some time earlier — unrelated to PHP2Shell. We quarantined it, kept the evidence and took the site out of service. Checks on the other sites found no signs of compromise, but a scan can't prove a server was never breached, and we told clients exactly that.

What's still on the list

Being honest about what isn't finished matters as much as the fix:

  • Some paid WordPress plugins need licence renewals before they can be updated.
  • The remaining PHP 7.4 systems need a planned migration to a supported version.
  • A few passwords and third-party keys that may have been exposed in old public backups need rotating.
  • Backups should be copied off the server, and restores should be rehearsed.

If you run a PHP website

  • Check which PHP version your host is actually running, and whether it's 8.2.35, 8.3.36, 8.4.27, 8.5.12 or newer.
  • If you're on PHP 8.1 or older, ask your host or developer how they're handling this — "we'll upgrade soon" isn't an answer.
  • Make sure there's a recent backup that has been tested, not just taken.
  • Remove old backup files and debug logs from your website folders.

If you're not sure where your site stands, get in touch and we'll check it for you.

Have a project like this?

Tell us what you need. We'll reply within one business day.

Book a free consultation →