eastbaycyber

How to Harden WordPress After a Breach (Step-by-Step)

FAQs 7 min read
EC
East Bay Cyber Editorial Team Reviewed 2026-05-16
Short answer

Treat the site as fully compromised. Take it offline or restrict access, preserve logs, restore WordPress/core/plugins/themes from trusted sources, and restore uploads from a verified clean backup. Rotate every password and secret (DB, WP users, SSH/SFTP, hosting, API keys), patch everything, remove unused plugins/themes, lock down admin access, and add WAF + monitoring.

WordPress hardening after a breach starts with one assumption: treat the site as fully compromised. That means you contain the incident, preserve evidence, restore from known-good sources (not “clean in place”), rotate every credential and secret, then lock down admin access and add monitoring so reinfection doesn’t linger unnoticed.

TL;DR - Assume full compromise: contain, preserve evidence, and restore from known-good sources (not “clean in place”). - Rotate all credentials/keys, patch core/plugins/themes, remove unused code, and enforce least privilege. - Add WAF, integrity monitoring, and log-based alerting to catch reinfection quickly.

Detailed Explanation

1) Contain first (stop the bleeding)

Your first goal is to prevent further damage—data theft, spam, lateral movement, or reinfection during cleanup.

Actions - Put the site into maintenance mode or restrict access at the edge (WAF, reverse proxy, basic auth). - Block suspicious IPs and disable nonessential access paths (SFTP/SSH accounts you don’t need right now). - Snapshot the environment if possible (VM snapshot, host snapshot). If not, at least copy evidence.

2) Preserve evidence (you’ll need it)

Even SMBs benefit from minimal forensics: it helps you confirm initial access, scope, and whether you’re getting reinfected.

Collect - Web server logs (access/error), PHP-FPM logs - WordPress debug log (if enabled), hosting/WAF logs - Database dump (read-only copy) - File tree listing and hashes (or at least timestamps)

3) Rebuild from known-good sources (prefer rebuild over “cleaning”)

The most reliable post-breach hardening is to reimage/rebuild: - Deploy a fresh OS/container/site instance - Install WordPress core from wordpress.org (or your known-good artifact repository) - Reinstall plugins/themes from trusted sources - Restore content (DB + uploads) only after validation

If you must clean in place, you still should replace core files and all plugin/theme code with known-good versions. Attackers commonly backdoor PHP in plugin directories, mu-plugins, or theme files, and hide persistence in scheduled tasks.

4) Rotate all credentials and secrets (not just WP admin)

Breaches often involve stolen creds. Rotating only the WordPress admin password is not enough.

Rotate - WordPress admin/editor accounts (force password reset; remove unknown users) - Database user password - wp-config.php salts/keys - Hosting control panel credentials - SSH/SFTP/FTP users (prefer SSH keys; disable FTP) - API tokens (payment, email, CRM, backups, CDN) - SMTP credentials (commonly abused for spam)

Password hygiene tip (post-breach): use a dedicated business password manager to generate and share strong, unique credentials. If you need one, 1Password is a common option for teams (Try 1Password →). For a deeper comparison, see our guide to /content/best-password-manager-for-small-business-2026/.

5) Patch and reduce attack surface

Most WordPress compromises still trace back to outdated plugins/themes, abandoned code, or exposed admin endpoints.

Do this immediately - Update WordPress core, all plugins, all themes. - Delete unused plugins/themes (inactive isn’t safe; the code remains reachable in many cases). - Replace “nulled”/pirated plugins/themes—these are a common infection vector.

6) Lock down authentication and admin access

Hardening after a breach should make re-entry difficult even if a password leaks again.

Recommended controls - Enforce MFA for all admin accounts (and ideally all users with elevated roles). - Limit /wp-admin and /wp-login.php exposure: - Allowlist office/VPN IPs where feasible - Add rate limiting and bot protection at WAF - Disable XML-RPC if you don’t need it (or restrict methods). - Enforce least privilege: most users should not be Administrators.

7) Secure file permissions, disable risky behaviors

Attackers love writable PHP directories and the ability to edit code from the dashboard.

Baseline - Disable file editing from WP admin. - Ensure correct ownership and permissions (principle: PHP process should not be able to modify arbitrary PHP files). - Prevent PHP execution in uploads where possible.

8) Add monitoring to catch reinfection (the step most teams skip)

Post-breach hardening is incomplete without detection. You want to know within minutes if a webshell returns or a rogue admin appears.

Minimum monitoring - File integrity monitoring (core, plugins, themes) - Alerts on new admin users, plugin installs, option changes - Log shipping (even simple) with alerts on suspicious patterns - Outbound traffic monitoring (unexpected POSTs, crypto miners, spam)

Optional but practical: run a reputable endpoint/host malware scan during and after recovery to confirm you didn’t miss droppers or cron persistence. Malwarebytes is widely used for malware detection and cleanup workflows (Get Malwarebytes →).


Practitioner Checklist (What to do next)

Immediate (0–4 hours)

  1. Restrict access / maintenance mode.
  2. Export logs + DB dump + file snapshot.
  3. Identify scope: single site vs. entire hosting account.
  4. Rotate hosting panel + SSH/SFTP creds; disable FTP.
  5. Take a clean backup of evidence (not for restore).

Short-term (today)

  1. Rebuild a clean instance (preferred).
  2. Reinstall WordPress core + plugins/themes from trusted sources.
  3. Restore DB and uploads from known-good backups; scan uploads.
  4. Rotate DB creds + WP salts.
  5. Enforce MFA and remove unknown WP users.
  6. Patch everything; delete unused plugins/themes.

Medium-term (this week)

  1. Add WAF rules/rate limiting for /wp-login.php and /wp-admin/.
  2. Implement integrity monitoring and log alerts.
  3. Review admin roles, editors, and installed plugins for necessity.
  4. Add backups with immutable storage or versioning.
  5. Run a post-incident review and document root cause.

Technical Notes: High-signal commands and config hardening

Replace WordPress core safely (don’t “surgically clean” core files)

From the WordPress root:

# Download official core and replace (adjust version as needed)
wp core download --force --skip-content

# Verify core checksums (good for detecting tampering)
wp core verify-checksums

Find recently modified PHP files (common persistence indicator)

# PHP files changed in last 7 days
find . -type f -name "*.php" -mtime -7 -print

# Look for suspicious functions (not proof, but strong leads)
grep -RIn --exclude-dir=node_modules --exclude-dir=vendor \
  -E "eval\(|base64_decode\(|gzinflate\(|str_rot13\(|shell_exec\(|system\(|passthru\(" .

Check for malicious scheduled tasks and must-use plugins

# Cron-like persistence in WordPress
wp cron event list

# Must-use plugins directory is a frequent hiding spot
ls -la wp-content/mu-plugins/

Rotate WordPress salts/keys

Update these in wp-config.php:

define('AUTH_KEY',         '...new...');
define('SECURE_AUTH_KEY',  '...new...');
define('LOGGED_IN_KEY',    '...new...');
define('NONCE_KEY',        '...new...');
define('AUTH_SALT',        '...new...');
define('SECURE_AUTH_SALT', '...new...');
define('LOGGED_IN_SALT',   '...new...');
define('NONCE_SALT',       '...new...');

Disable theme/plugin editor (prevents easy backdoor edits in admin)

In wp-config.php:

define('DISALLOW_FILE_EDIT', true);

Lock down file permissions (typical baseline; adjust to your hosting model)

# Directories 755, files 644 (common baseline)
find . -type d -exec chmod 755 {} \;
find . -type f -exec chmod 644 {} \;

# wp-config.php stricter
chmod 600 wp-config.php

Prevent PHP execution in uploads (Apache example)

Create wp-content/uploads/.htaccess:

<FilesMatch "\.php$">
  Deny from all
</FilesMatch>

For Nginx (server block/location example):

location ~* ^/wp-content/uploads/.*\.php$ {
  deny all;
}

Review WordPress users and remove unknown admins

wp user list --fields=ID,user_login,user_email,roles,registered
wp user delete <ID> --reassign=<another_user_id>

Log patterns worth hunting (quick triage)

In web access logs, look for: - High-volume POSTs to /wp-login.php - Requests to /wp-admin/admin-ajax.php with unusual parameters - Direct hits to suspicious paths like: - /wp-content/uploads/*.php - /wp-includes/*.php with odd query strings - Random .php in plugin/theme directories

Example grep:

grep -E "wp-login\.php|xmlrpc\.php|admin-ajax\.php|/uploads/.*\.php" /var/log/nginx/access.log*

Common Misconceptions

  1. “I removed the malware file, so we’re good.”
    Not unless you’ve removed the initial access vector (vulnerable plugin, stolen creds) and any persistence (mu-plugins, cron events, hidden admin users, modified plugin files).

  2. “Changing the WordPress admin password is enough.”
    Attackers often have hosting panel access, DB creds, SSH/SFTP credentials, or API tokens. Rotate everything, including salts and database passwords.

  3. “Deactivating a plugin fixes the risk.”
    Inactive plugins still exist on disk and can be directly invoked if vulnerable or if an attacker already planted a backdoor there. Delete unused plugins/themes.

  4. “Backups guarantee quick recovery.”
    Backups can be infected too. You need known-good restore points and a validation step (checksum verification, malware scanning, and log review).

  5. “Security plugins alone will prevent reinfection.”
    They help, but they’re not a substitute for patching, least privilege, hardened hosting, and monitoring.


This article may contain affiliate links. We earn a commission on qualifying purchases at no extra cost to you.

Last verified: 2026-05-16

Disclaimer: This article may contain affiliate links. We earn a commission on qualifying purchases at no extra cost to you.