WordPress powers 43% of the web. That makes it the largest target on the internet. Not because it’s insecure by default, but because attackers optimize for scale. One exploit that works on 43% of websites is worth developing.

The good news: the vast majority of successful WordPress attacks exploit a small set of well-known weaknesses. Patch these five areas and you’ve eliminated roughly 95% of your attack surface.

This is the checklist we apply to every WordPress installation we manage. Ordered by impact.

1. Update Everything (The Unsexy Fix That Prevents Most Attacks)

Sucuri’s annual hacked website report consistently shows that 90%+ of compromised WordPress sites were running outdated software at the time of the breach. Not zero-day exploits. Not sophisticated attacks. Just unpatched known vulnerabilities.

WordPress Core

Enable automatic minor updates (they’re on by default since WordPress 3.7). For major updates, test on staging first, then apply within 72 hours of release.

Add this to wp-config.php if automatic minor updates have been disabled:

define( 'WP_AUTO_UPDATE_CORE', 'minor' );

Plugins

Plugins are the primary attack vector. They account for roughly 97% of WordPress vulnerabilities. The discipline here is straightforward:

  • Update weekly. Set a recurring calendar event.
  • Audit quarterly. Remove any plugin you’re not actively using. Deactivated plugins are still exploitable if the files exist on the server.
  • Check before installing. Look at the plugin’s last update date, active installations, and support forum responsiveness. If it hasn’t been updated in 12+ months, find an alternative.
  • Limit total plugins to under 25. Every plugin is a potential entry point. Most sites can function well with 10-15.

Themes

Same rules as plugins. Delete unused themes. Keep only your active theme and one default theme (for fallback).

PHP Version

Run PHP 8.2 or newer. Older PHP versions don’t receive security patches. PHP 7.4 reached end-of-life in November 2022, yet roughly 30% of WordPress sites still run it. This is an open door.

2. Authentication Hardening

Brute force attacks against wp-login.php are constant. Every WordPress site on the internet receives them. The question is whether your authentication layer holds.

Strong Passwords (Enforced, Not Suggested)

WordPress suggests strong passwords but doesn’t require them. Fix this:

  • Require minimum 16 characters for all admin accounts.
  • Use a password manager. If your team isn’t using one, that’s a higher priority than any security plugin.
  • No password reuse. This is the single most common credential compromise vector. A password leaked from an unrelated service gets stuffed into your wp-login.php.

Two-Factor Authentication (2FA)

Non-negotiable for any admin or editor account. Period.

Recommended plugins:

  • WP 2FA — clean interface, supports TOTP (authenticator apps) and email codes
  • Two-Factor — the official WordPress.org plugin, lightweight and reliable

TOTP-based 2FA (Google Authenticator, Authy, 1Password) is strongly preferred over SMS-based 2FA. SIM-swapping attacks make SMS unreliable for high-value targets.

Login Attempt Limiting

Limit failed login attempts to 5 per IP address, with a 15-minute lockout. This stops automated brute force attacks cold.

Options:

  • Limit Login Attempts Reloaded — simple, focused, low overhead
  • Wordfence — includes this as part of a broader security suite
  • Server-level rate limiting via Nginx or Apache (preferred if you have server access)

Change the Login URL

This is security through obscurity — it won’t stop a determined attacker, but it eliminates 99% of automated bot traffic hitting your login page. Less noise in your logs, less server load.

WPS Hide Login handles this with zero configuration complexity.

3. File Permissions and wp-config Hardening

File Permissions

The correct permission structure for WordPress:

PathPermissionWhy
Directories755Owner can read/write/execute; group and others can read/execute
Files644Owner can read/write; group and others can read only
wp-config.php400 or 440Owner can read only; no one else has access
.htaccess644Readable by Apache, writable by owner only

If your hosting provider set everything to 777 (full access for everyone), that’s a critical vulnerability. Fix it immediately.

wp-config.php Hardening

This file contains your database credentials and authentication keys. Harden it:

Move it above the web root. WordPress will automatically look one directory above the web root for wp-config.php. This prevents direct access via URL.

Set unique authentication keys and salts. Generate fresh ones at api.wordpress.org/secret-key/1.1/salt/ and paste them into your config. Rotate these annually or immediately after any suspected compromise.

Disable file editing:

define( 'DISALLOW_FILE_EDIT', true );

This removes the Theme Editor and Plugin Editor from the WordPress admin panel. If an attacker compromises an admin account, they can’t inject code through the built-in editors.

Force SSL for admin:

define( 'FORCE_SSL_ADMIN', true );

Disable XML-RPC if you don’t need it (most sites don’t). XML-RPC is a legacy API that enables brute force amplification attacks. Disable it at the server level:

# .htaccess
<Files xmlrpc.php>
  Order deny,allow
  Deny from all
</Files>

Or via Nginx:

location = /xmlrpc.php {
  deny all;
  access_log off;
  log_not_found off;
}

4. Web Application Firewall (WAF)

A WAF inspects incoming traffic and blocks known attack patterns before they reach WordPress. This is your first line of defense against SQL injection, cross-site scripting (XSS), and file inclusion attacks.

These sit between visitors and your server, filtering traffic at the network edge:

  • Cloudflare — free tier includes basic WAF rules. Pro ($20/month) adds managed rulesets. Best value for most sites.
  • Sucuri Firewall — $199/year. Includes CDN, DDoS protection, and malware cleanup guarantee. Strong choice for sites that have been hacked before.

Application-Level WAF

These run as WordPress plugins. They catch threats that pass through the cloud WAF:

  • Wordfence — the most comprehensive WordPress security plugin. Free tier is solid. Premium ($119/year) adds real-time firewall rule updates and country blocking.
  • NinjaFirewall — lighter weight than Wordfence, runs as a standalone firewall before WordPress loads. Better performance for high-traffic sites.

Layered Approach

The best configuration uses both: Cloudflare at the edge (stops 95% of malicious traffic before it reaches your server) plus Wordfence or NinjaFirewall at the application level (catches the 5% that gets through).

5. Database and Backup Security

Change the Database Prefix

WordPress defaults to wp_ as the database table prefix. Every automated SQL injection attack assumes this prefix. Changing it to something random (xk7m_, for example) breaks those automated scripts.

Set this during installation in wp-config.php:

$table_prefix = 'xk7m_';

Changing the prefix on an existing site requires updating every table name and several option values. Use a plugin like Brozzme DB Prefix or do it manually with caution and a fresh backup.

Backup Strategy

Backups are your last line of defense. When everything else fails, a clean backup is the difference between a 2-hour recovery and a 2-week rebuild.

Requirements:

  • Daily automated backups of both files and database
  • Off-site storage (not on the same server as your site)
  • 30-day retention minimum
  • Tested restoration — verify your backup actually works at least quarterly

Recommended tools:

  • UpdraftPlus — free version handles daily backups to Google Drive, Dropbox, or S3
  • BlogVault — $89/year, includes real-time backups, staging, and one-click restore
  • Server-level snapshots — if your host offers automated server backups (DigitalOcean, Kinsta, WP Engine), enable them as a secondary backup layer

Server-Level Hardening

These configurations happen outside WordPress, at the server or hosting level:

Disable Directory Browsing

Prevent visitors from seeing your file structure:

# .htaccess
Options -Indexes

Block PHP Execution in Upload Directories

Attackers often upload malicious PHP files disguised as images. Block execution in /wp-content/uploads/:

# wp-content/uploads/.htaccess
<Files *.php>
  deny from all
</Files>

Security Headers

Add these to your server configuration:

X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
Content-Security-Policy: [configured for your specific site]
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=()

HTTP/2 or HTTP/3

Ensure your server supports HTTP/2 at minimum. Most modern hosts do. HTTP/3 (QUIC) is available on Cloudflare and major CDNs. Beyond performance benefits, modern protocols have better resistance to certain network-level attacks.

Monitoring: Know When Something Goes Wrong

Security without monitoring is hope-based defense. You need to know when files change, when login patterns shift, and when new admin accounts appear.

File Integrity Monitoring

Wordfence includes this by default — it compares your WordPress core files, plugin files, and theme files against known-good versions. Any unauthorized change triggers an alert.

Activity Logging

Install WP Activity Log (or similar). It records every action in the admin panel: who logged in, what they changed, when they changed it. Essential for multi-user sites and invaluable during incident investigation.

Uptime Monitoring

Use an external service (UptimeRobot, Pingdom, or Better Uptime) to check your site every 60 seconds. If it goes down, you should know before your customers do.

Incident Response: When You’ve Been Breached

Even with perfect hardening, breaches happen. Here’s the response protocol:

Immediate (First 30 Minutes)

  1. Don’t panic, but don’t wait. Every minute the attacker has access, the damage compounds.
  2. Take the site offline. Put up a maintenance page. This stops ongoing data exposure and prevents the attacker from covering their tracks.
  3. Change all passwords. WordPress admin, database, FTP/SFTP, hosting panel, CDN. All of them. From a device you trust.
  4. Revoke all active sessions. In WordPress: go to Users, edit each admin account, click “Log Out Everywhere Else.”

Investigation (Hours 1-4)

  1. Check access logs. Identify the entry point. Look for POST requests to unusual file paths, especially in /wp-content/uploads/.
  2. Scan for malware. Use Sucuri SiteCheck, Wordfence scan, or MalCare to identify infected files.
  3. Review file modification dates. Any file modified during the attack window is suspect.
  4. Check for backdoors. Attackers almost always install persistence mechanisms. Common locations: wp-content/uploads/, wp-includes/, theme functions.php.

Recovery (Hours 4-24)

  1. Restore from clean backup. If you have a backup from before the compromise, restore it.
  2. If no clean backup exists: remove all infected files manually, reinstall WordPress core, reinstall all plugins and themes from fresh sources.
  3. Update everything. Core, plugins, themes, PHP.
  4. Reapply hardening. Run through this entire checklist again.
  5. Request Google review if the site was flagged (via Google Search Console).

Post-Incident (Week 1)

  1. Document what happened. Entry point, timeline, impact, response.
  2. Address the root cause. If an outdated plugin was the vector, implement automated updates.
  3. Monitor closely for 30 days. Attackers often return through backup access points.

The 80/20 of WordPress Security

If you do nothing else, do these three things:

  1. Keep everything updated. Weekly. No exceptions.
  2. Enable 2FA on all admin accounts. Today.
  3. Install a WAF. Even Cloudflare’s free tier dramatically reduces your exposure.

These three actions, done consistently, prevent the vast majority of WordPress compromises. The rest of this checklist is important, but these three are foundational.