Why Does My WordPress Site Keep Getting Hacked?
Diagnosis

Why Does My WordPress Site Keep Getting Hacked?

If you've cleaned up your WordPress site once, twice, three times — and it keeps coming back — you don't need another generic "WordPress security checklist." You need to find the thing your last cleanup missed. Repeat infections almost always come down to one of two things: a backdoor that survived the cleanup, or an entry point that was never actually closed. This page covers what to look for, where to look for it, and when to stop trying and rebuild from scratch.

You cleaned up but missed something. Here's the pattern.

A successful cleanup looks like this: malware removed, plugins updated, passwords changed, scan comes back clean. Two weeks later: same domain, same redirects, same Google warning. The reason is almost never that "they hacked you again" in the cinematic sense — it's that they never left.

The pattern: when an attacker first compromises a site, they don't just install one piece of malware. They install several backdoors in unrelated places, often days apart. The visible malware (the redirects, the spam pages, the injected ads) gets all the attention during cleanup. The hidden backdoors — small files designed to look innocent — survive. Two weeks later, the attacker uses one of the backdoors to walk back in and reinstall the visible malware. Round two starts.

The fix isn't a different security plugin or a better firewall. It's a forensic mindset: assume you missed something, and start looking systematically.

The 5 places backdoors hide that most cleanups miss

First: PHP files inside /wp-content/uploads/. This folder is supposed to contain images and PDFs only. Any .php file here is suspicious — WordPress never puts executable code in uploads. Backdoors hide as wp-includes.php, class-config.php, anything that sounds vaguely WordPress-y. Run `find wp-content/uploads -name "*.php"` from SSH. If anything comes back, that's the backdoor.

Second: modified core files. Attackers modify legitimate WordPress files to add a small malicious snippet at the top — usually wp-load.php, wp-blog-header.php, or index.php. The file still works normally, but the snippet runs on every page load. Compare every core file against the official release using `wp core verify-checksums` (WP-CLI).

Third: fake "must-use" plugins. The wp-content/mu-plugins/ directory loads PHP files automatically without showing them in the admin plugin list. A backdoor here is invisible to anyone clicking around in wp-admin. Check the directory directly via SSH or your file manager.

Fourth: database wp_options rows. Attackers add custom rows to the options table containing serialised malicious code. They get loaded on every page. Query: `SELECT option_name FROM wp_options WHERE option_value LIKE '%base64_decode%' OR option_value LIKE '%eval(%';`

Fifth: scheduled cron jobs. WordPress and your hosting both run cron tasks. Attackers add their own scheduled task that re-downloads the malware on a timer — so even if you delete the visible files, the cron job re-fetches them within 24 hours. Run `wp cron event list` and look for hooks you don't recognise.

How attackers keep coming back after a "clean" cleanup

Modern WordPress malware is designed for persistence. Three mechanisms run quietly behind the scenes.

The scheduled re-installer is the most common. After the initial compromise, the attacker schedules a wp-cron event (or a system cron job at the OS level if they have shell access) that runs daily and checks if the visible malware is still present. If it isn't, it re-downloads from a remote server and reinstalls. From your side, the site looks clean for 24 hours then "gets hacked again."

The abandoned admin account is the slow one. During the initial breach, attackers create a new admin user — often with an innocuous-looking name like "wpadmin" or "support" or your own first name with a small variation. Most cleanups change the original admin password but never check the user list for unfamiliar accounts. The attacker logs in next month with the credentials they created themselves.

The server-level rule is the worst. If your shared hosting account was compromised at the OS level (rare on managed hosts, possible on cheap shared hosting), attackers can add Apache/Nginx rules, PHP auto-prepend directives, or system cron jobs that re-inject malware regardless of what you do at the WordPress level. WordPress-level cleanup will not fix this — you need your host involved.

The "did I really clean up?" forensic checklist

Work through this list before declaring a site clean.

1. File integrity check. Run `wp core verify-checksums` and `wp plugin verify-checksums --all`. Anything flagged is either a legitimate customisation you forgot about or a tampered file.

2. Recent file modifications. From SSH: `find . -type f -mtime -30 -not -path "./wp-content/cache/*"`. Lists every file modified in the last 30 days. Most should be ones you knowingly edited.

3. /wp-content/uploads/ audit. As above — no .php files allowed here.

4. mu-plugins/ directory check. List every file. Anything you didn't put there is suspicious.

5. User audit. `wp user list --role=administrator`. Verify every account is one you created. Delete anything you don't recognise.

6. Cron audit. `wp cron event list`. Look for unusual hooks — anything not from WordPress core, your installed plugins, or your theme.

7. wp_options audit. Run the SQL query in section 2.

8. .htaccess audit. Open the file and read every line. Backdoor rules often hide as long base64-looking strings.

9. Hosting malware scan. Most cPanel hosts (SiteGround, Bluehost, Namecheap) have a malware scanner in the hosting panel. Run it. It catches things WordPress-level scanners miss.

10. Re-scan with a security scanner after cleanup. This is what GuardingWP is for — it tells you which exploitable entry points are still open from the outside.

When to stop patching and rebuild

If you've worked through the checklist twice and the site is still getting hit, stop. Continuing forensic cleanup is more expensive than starting fresh.

The clean rebuild approach: spin up a brand-new WordPress install on a new database (different prefix, different password). Manually copy your content — posts, pages, media files, exported via the standard WordPress export tool — but no plugin/theme files, no .htaccess, no wp-config.php. Reinstall plugins from the official repository, fresh copies. Rebuild your theme from your version control or from the original purchase, never from the live site.

This is more work than another cleanup, but it's finite work. Three days of rebuilding ends the cycle. Three months of repeated cleanups doesn't.

The economic threshold is simple: if you've spent more than 8 hours total on cleanup and re-cleanup, the rebuild is already cheaper.

Related fix guides

GuardingWP checks your site for the 11 most common WordPress vulnerabilities — plus scans your installed plugins against the known CVE database. Free, no account required.

Scan to find what your last cleanup missed →

Break the re-infection cycle

If your site keeps getting hacked, the entry point is still there. The Forensic Toolkit runs a full SSH-based audit that surfaces what surface scanners miss — modified core files, hidden admin users, malicious cron jobs, and database injections. Run it once, find the persistence mechanism, end the cycle.

Get the Forensic Toolkit — from $25 →

Prefer to have this handled for you? Get this fixed — Full Hardening ($149)