WordPress Security Basics That Stop Most Attacks
When I clean up a compromised WordPress site, the cause is almost never a sophisticated, targeted attack. It's an outdated plugin with a known vulnerability that was patched months ago, a wp-admin login with a password that's been breached in some unrelated leak, or an old theme that hasn't been touched since the site launched and has a file upload vulnerability nobody's looked at since. WordPress's popularity means automated scanners are constantly probing for exactly these things, and the basics below are what closes that door.
Updates: the single biggest factor
Most WordPress compromises trace back to a plugin or theme with a publicly known vulnerability that simply hadn't been updated. WordPress core handles security updates automatically by default, but plugins and themes don't unless configured to:
// wp-config.php
add_filter('auto_update_plugin', '__return_true');
add_filter('auto_update_theme', '__return_true');
For sites where a plugin update breaking something is a bigger concern than the security risk of not updating, a staging environment that gets updates first, with production following a few days later, is a reasonable middle ground. What's not reasonable is "we'll update when we get to it," because that's exactly the window automated scanners are looking for.
Remove what isn't being used
Every inactive plugin and theme is still code sitting on the server, and "inactive" doesn't mean "not exploitable", a vulnerability in a deactivated plugin's files can often still be reached directly if the file itself is accessible. The fix isn't deactivating, it's deleting:
wp plugin list --status=inactive
wp plugin delete <plugin-name>
If it's needed again later, it can be reinstalled in thirty seconds. Sitting unused on disk, it's pure attack surface with no benefit.
Login security: where most automated attacks land
/wp-login.php and /xmlrpc.php are hit by automated login attempts constantly, regardless of how obscure the site is. A few changes address most of this:
Strong, unique passwords and 2FA for every account with publish or admin access, not just the main admin account, a contributor account with a weak password is still a foothold.
Limiting login attempts, either via a plugin or, at the server level, a Fail2ban jail watching for repeated failed logins against wp-login.php:
# /etc/fail2ban/jail.local
[wordpress]
enabled = true
filter = wordpress
logpath = /var/log/nginx/access.log
maxretry = 5
bantime = 3600
Disabling XML-RPC if nothing (no app, no Jetpack-style integration) actually uses it, since it's a common target for both brute-force attempts and amplification in pingback-based attacks, and most sites have no legitimate use for it.
Locking down the admin area
DISALLOW_FILE_EDIT removes the built-in theme and plugin file editor from the WordPress admin, the editor that lets anyone with admin access edit PHP files directly through the browser. If an admin account is ever compromised, this is one less way for that compromise to turn into arbitrary code execution:
// wp-config.php
define('DISALLOW_FILE_EDIT', true);
File permissions matter too, WordPress's own recommendation of 644 for files and 755 for directories, with wp-config.php at 600, means that even if a vulnerability allows writing to the filesystem, it's constrained by what the web server's user is actually permitted to touch.
A web application firewall catches what's not yet patched
Updates handle known vulnerabilities once a patch exists. The gap between a vulnerability being discovered and a patch being released, and the gap between a patch being released and every site actually applying it, is where a web application firewall earns its place. ModSecurity with the OWASP Core Rule Set, or a plugin-based WAF, blocks a lot of generic exploit patterns (SQL injection attempts, path traversal, common payload signatures) regardless of which specific plugin they're targeting, which means it's useful even against vulnerabilities nobody's written a specific rule for yet.
Why these basics are still the answer
None of this is advanced, and that's the point. The vast majority of WordPress compromises aren't zero-days, they're known issues with available fixes that simply weren't applied, on sites where login security was an afterthought. Updates, removing unused code, login hardening, and a WAF address the categories that automated attacks actually target, in roughly the order of how often each one is the actual cause. Getting these right doesn't make a site invulnerable, but it moves it out of the enormous pool of sites that automated scanners compromise without any real effort.