The morning my websites started selling Prada in Japanese

Two of my WordPress sites were quietly hacked overnight. A team of AI agents found it, cleaned it up and locked the doors the same day.

On a normal Monday morning, my AI SEO assistant ran its weekly check on two WordPress sites I look after and found something odd. To me, and to anyone visiting, both sites looked completely normal. To Google, they were Japanese online shops selling Prada phone cases and Moncler.

That's a "Japanese keyword hack", and the clever, nasty part is the cloaking. The sites served the real homepage, about 55 KB, to normal visitors. When a request said it was Googlebot, it got a 224 to 250 KB spam shop page instead. Every sitemap listed 1,902 pages, and only one of them was real. The other 1,901 were spam shop addresses, all dated that morning.

If I'd been relying on looking at the sites myself, I wouldn't have seen a thing.

What had actually happened

A second assistant, the one that looks after the WordPress side, took the backups, pulled them apart and worked out what was going on. It was a lot worse than a few dodgy pages:

  • The main index.php on each site had been replaced. It quietly asked a remote server what to show each visitor, then fell back to the real site if the answer was "nothing".
  • There was a dropper disguised as a PNG image inside a fake plugin folder, plus a webshell hidden as a GIF, plus extra back doors on one site.
  • One site had gained a new administrator account, with a random name, created at 06:30 that morning.
  • Thousands of .htaccess files had been planted across the hosting account, which locked me out of installing plugins or running updates from the WordPress dashboard. I'd assumed that was a host restriction. It wasn't. It was the malware protecting itself.

The main wave hit both sites eight seconds apart at about 5.43am, with an earlier wave of back doors from around 1.30am. The last clean backups were from a few days before.

As for how it got in, the honest answer is that it's not proven. The most likely route was the Bricks theme on one site. It was still on version 1.9.1.1, from October 2023, which has a known flaw (CVE-2024-25600) that lets anyone run code on the server without logging in. It was fixed in 1.9.6.1 and has been mass-exploited since February 2024. Both sites shared one hosting account, so once the attacker was in one, the other was right there.

Why we didn't just clean it

The obvious move is to find the bad files and delete them. The trouble came when we scanned the whole hosting account, around 40,000 files. It turned up far more back doors than the backups had shown, including on old parked domains I'd stopped thinking about. Miss a single one and the attacker walks straight back in.

So the plan became a wipe and rebuild:

  1. Keep the hacked files off the web as evidence.
  2. Build clean copies with official WordPress, the current version of Bricks and genuine plugins, every file checked against the official checksums.
  3. Restore uploads from the clean backups, scan them, and reconnect the existing databases, which turned out to be clean.
  4. Upload each clean copy beside the hacked one and swap them over, so each site was only down for a few minutes.

The first site was swapped at 15:22 and the second at 16:18, a little over eight hours after the problem was spotted. Afterwards, Googlebot and normal visitors got the same real page again, and each sitemap went back to listing one honest URL.

The bits that needed a human

The AI did the investigation, the rebuild and the checking, but some of it had to be me. I approved the emergency fix. I created a temporary FTP account, kept my PC awake during the file copy and brought it back online when it dropped halfway through. I checked for rogue cron jobs, changed every password, deleted the FTP account when we'd finished, and did the Google Search Console requests myself.

That split felt right. It asked before doing anything drastic, and the keys stayed with me.

Locking the doors

That evening I asked how we stop this happening again. Here's what we ended up doing:

  • Spam pages now say "gone". A free Cloudflare Worker returns 410 Gone for the spam addresses, which tells Google to drop them rather than keep checking.
  • Updates are automatic for WordPress, plugins and themes, so nothing gets two years out of date again.
  • The login is behind a firewall. Cloudflare challenges anyone hitting the login page, and a security plugin locks out repeated failed logins.
  • One admin per site. Each site has exactly one admin account, and nothing else.
  • There's a weekly check for new admins, changed files, backups and fresh spam in Google.

There are still a couple of loose ends, such as connecting off-server backups and turning on two-factor login, and Google takes days to weeks to forget spam pages. But the sites are clean.

What I took from it

Nobody was attacking me in particular. A bot found an old copy of Bricks with a known hole, and everything else was automated. The fix was boring: keep things updated, and don't put several sites in one account where one break-in reaches all of them.

The scare also settled a decision I'd been going back and forth on. The new site is going to be static, with no WordPress, no plugins and no login page for anyone to hammer.