By default, WordPress lets anyone try to log in as many times as they want. No limit. No lockout. No delay.
That means a bot can sit on your login page and try 10,000 password combinations without WordPress batting an eye. Each attempt gets a fresh chance. Each gets a helpful “incorrect password” message confirming the username exists. It’s the digital equivalent of leaving your front door unlocked and putting a sign that says “keep trying.”
This is one of the first things I fix on every new WordPress site. It takes less than a minute, and it stops the most common attack vector on the internet.
What is a brute force attack?
A brute force attack is simple: an automated script tries every possible username-password combination until it finds one that works. There’s no cleverness involved — just speed and persistence.
Modern attack tools can cycle through thousands of combinations per minute. They pull passwords from leaked database dumps (billions of credentials are publicly available), common password lists, and dictionary attacks. If your admin password is anything resembling a real word or a common pattern, it’s in those lists.
WordPress makes this worse by confirming whether a username exists. Try logging in with a username that doesn’t exist — WordPress says “Unknown username.” Try a real username with the wrong password — WordPress says “The password you entered is incorrect.” That’s valuable information for an attacker. They can first discover valid usernames, then focus their password guessing on those accounts.
Why should you care?
It’s not theoretical. Every WordPress site gets brute-forced. Not might, not could — does. Check your server logs. The requests are already there. The only question is whether your passwords are strong enough to survive and whether the constant hammering is degrading your site performance.
Server overload. Each login attempt triggers a full WordPress authentication cycle: PHP loads, the database is queried, password hashing runs (which is intentionally CPU-intensive for security). A few thousand attempts per hour means your server is spending real resources on attackers instead of visitors.
The system.multicall amplifier. If XML-RPC is still enabled on your site, attackers can use system.multicall to send hundreds of login attempts in a single HTTP request, completely bypassing per-request rate limits. This is why XML-RPC should also be disabled (see our related post).
Account compromise is just the start. If an attacker guesses a valid admin password, the damage isn’t just a defaced homepage. They can install backdoor plugins, inject malware into your theme files, redirect your visitors to phishing sites, steal customer data from WooCommerce, or use your server to send spam. Recovery takes hours to days, and some damage — like a Google “This site may be hacked” warning — can take weeks to clear.
The quick fix
Add this to a site-specific plugin:
// Simple login attempt limiter
add_filter( 'authenticate', function( $user, $username, $password ) {
if ( empty( $username ) ) return $user;
$ip = $_SERVER['REMOTE_ADDR'];
$transient_key = 'login_attempts_' . md5( $ip );
$attempts = get_transient( $transient_key ) ?: 0;
// Lock out after 5 failed attempts for 15 minutes
if ( $attempts >= 5 ) {
return new WP_Error(
'too_many_attempts',
'Too many failed login attempts. Please try again in 15 minutes.'
);
}
return $user;
}, 30, 3 );
// Increment counter on failed login
add_action( 'wp_login_failed', function( $username ) {
$ip = $_SERVER['REMOTE_ADDR'];
$transient_key = 'login_attempts_' . md5( $ip );
$attempts = get_transient( $transient_key ) ?: 0;
set_transient( $transient_key, $attempts + 1, 15 * MINUTE_IN_SECONDS );
});
// Reset counter on successful login
add_action( 'wp_login', function() {
$ip = $_SERVER['REMOTE_ADDR'];
delete_transient( 'login_attempts_' . md5( $ip ) );
});
This gives you basic protection: after 5 failed attempts from the same IP, that IP is locked out for 15 minutes. Simple but effective against most automated attacks.
Limitations of this approach: It only tracks by IP address. Distributed attacks using thousands of IPs will get around it. It doesn’t handle proxy/CDN headers (if you’re behind Cloudflare, all requests look like they come from the same IP unless configured properly). And it stores attempt data in WordPress transients, which means database writes for every failed login.
The one-click solution
OvKit includes Limit Login Attempts under Features → Security. It handles the edge cases the simple snippet misses: proper IP detection behind Cloudflare and reverse proxies, configurable attempt limits and lockout durations, progressive lockout (the lockout period doubles on repeated offenses), and email notifications when an account gets targeted.
One toggle, no configuration needed for the defaults. Adjust the thresholds if you want, but the defaults (5 attempts, 15-minute lockout, escalating) work for most sites.
What happens after you fix this?
- Brute force attacks become impractical — at 5 attempts per 15 minutes, testing 10,000 passwords would take over 20 days from a single IP
- Server load from bot traffic drops — locked-out IPs get a quick error response instead of full authentication cycles
- Your admin accounts are protected — even a moderately strong password becomes nearly uncrackable with rate limiting in place
- You get visibility into attacks — lockout logs show you which usernames are being targeted and from where
Combine login limiting with hiding the login page and disabling XML-RPC, and you’ve closed the three main brute force vectors on WordPress.
FAQ
Will this lock me out of my own site if I forget my password?
It can, temporarily. If you exhaust your attempts, you’ll need to wait for the lockout period to expire. With OvKit, the default is 15 minutes — annoying but not catastrophic. You can also access your site via FTP and deactivate the plugin to remove the lockout immediately. This is why having FTP access credentials stored safely is always a good idea.
Does this protect against distributed brute force attacks?
Basic IP-based limiting doesn’t fully protect against attacks from thousands of different IPs. For that level of protection, you need a Web Application Firewall (WAF) like Cloudflare or Sucuri that can detect distributed attack patterns. Login limiting is still valuable — it stops the majority of attacks that come from single IPs or small clusters.
Should I use this together with two-factor authentication?
Yes, absolutely. Login attempt limiting stops automated attacks. Two-factor authentication stops attackers who somehow obtain a valid password (from a data breach, for example). They complement each other. Neither one alone is sufficient — together, they make unauthorized access extremely unlikely.
Related reads: