RevealTheme logo
Back to Blog

A WordPress Compromise: How It Was Caught and Recovered

A WordPress Compromise: How It Was Caught and Recovered
The RevealTheme Team

By

·

The first sign that something was wrong was a Google Search Console alert: "Security issues detected on your site." The alert arrived at 2:47 PM. By 2:51 PM the source of the compromise was identified. By 4:21 PM the site was clean and functioning normally. The full timeline and the specific decisions that made the recovery fast are useful for anyone who hasn't dealt with a WordPress compromise before.

The site was a client business site, roughly 18 months old, running on Hostinger Business hosting. Around 4,000 monthly visits, no significant traffic spikes recently. WordPress 6.7.1, Astra theme, 12 active plugins including Wordfence Free.

What happened

An outdated plugin (a contact-form variant the previous developer had installed and forgotten) had a known SQL injection vulnerability published 11 days before the compromise. The plugin had been auto-updated for routine patches but the developer hadn't pushed a fix for this specific CVE yet. The vulnerability was being actively exploited via a botnet running automated WordPress scans.

An attacker gained admin-level access through the vulnerability, created a new admin user (with the username "support_admin" to look legitimate), installed a malicious plugin disguised as a security tool, and uploaded a PHP backdoor file in the uploads directory.

How the compromise was detected

The Google Search Console alert fired because the malicious plugin had injected hidden links into the site's footer pointing to spam content. Google's crawler detected the spam injection and flagged the site as compromised.

The same compromise would have been caught within hours by Wordfence's scheduled scan, but the Search Console alert arrived first. Multiple monitoring systems catching the same issue independently is a feature, not a problem; the redundancy means you find out fast through whichever channel triggers first.

The recovery sequence

Step 1, 2:51 PM. Take the site offline temporarily with a maintenance mode plugin. This prevents the compromise from worsening while we work and stops visitors from being exposed to the spam injections.

Step 2, 2:54 PM. Run Wordfence's scan in "Detailed" mode. The scan found three things: the suspicious admin user, the malicious plugin (named "Security Enhancement Tool" by the attacker), and the PHP backdoor file in uploads. Wordfence didn't catch one additional modification: a few lines inserted into the active theme's functions.php file.

Step 3, 3:02 PM. Delete the malicious plugin via Wordfence's quarantine. Delete the suspicious admin user. Delete the backdoor PHP file in uploads.

Step 4, 3:08 PM. Examine the theme's functions.php manually. Found two suspicious lines that loaded remote content. Removed them.

Step 5, 3:14 PM. Change all admin passwords. Force re-login for all existing user sessions (Users → Sessions).

Step 6, 3:18 PM. Identify the vulnerable plugin that allowed initial access. The Wordfence scan log showed which plugin's directory had been written to. Updated the plugin to its latest version (which had patched the vulnerability 4 days earlier).

Step 7, 3:25 PM. Run Wordfence's scan again from scratch. Clean.

Step 8, 3:32 PM. Reactivate the site (deactivate maintenance mode).

Step 9, 3:45 PM. Submit a re-review request in Google Search Console for the security issues warning.

Step 10, 4:21 PM. Verify the site is functioning normally for visitors. Test admin login, frontend rendering, contact form submission. All working.

What made the recovery fast

Three things specifically. First, the site had a working backup from the morning. Even though the backup wasn't used (the manual recovery was faster), having it available meant we had a fallback if the manual recovery failed.

Second, Wordfence's scan caught most of the malicious additions automatically. The 5% it missed (the functions.php modifications) required manual review but was straightforward to identify because we knew the compromise pattern.

Third, the original plugin vulnerability was already known and patched. The plugin developer's fix was 4 days old at time of compromise. Updating the plugin was a single click rather than waiting for a fix to be developed.

What I'd skip next time

I'd skip Wordfence's "Detailed" scan and run "Quick" scan first to identify the obvious issues, then do detailed review afterward. The detailed scan takes 8-12 minutes on a small site; the quick scan takes 1-2 minutes and catches the obvious malware additions immediately.

For this site I also implemented a stricter policy after the recovery: weekly Wordfence scans (was scheduled but not running consistently), automatic plugin updates enabled (was manual), and a removal of the contact-form plugin that caused the issue (replaced with WPForms Lite for the limited contact form functionality the site actually needed).

The total time invested: 90 minutes for recovery, plus another 30 minutes implementing the additional security measures. The site has been clean for the 8 months since.