Type something to search...
What is a brute force attack and how to stop it?

What is a brute force attack and how to stop it?

A brute force attack is an attempt to break into an account by automatically trying huge numbers of username and password combinations until one works. You stop it by making each guess expensive and unlikely to succeed: use long, unique passwords, enable two-factor authentication, limit and rate-limit login attempts, and block or challenge the automated traffic before it reaches your login form.

Brute force attacks are among the most common attacks any website sees. If you look at the logs of a typical WordPress site, you'll likely find login attempts from unfamiliar IPs every day. This article explains how brute force attacks work, the different variations, how to spot them, and a layered set of defenses you can put in place, with configuration examples for WordPress, Nginx, Apache, and Fail2Ban.

How Does a Brute Force Attack Work?

At its simplest, an attacker points an automated tool at a login form and submits guesses as fast as the server will accept them. Because it's automated, the attacker doesn't need to be present, and one operator can target thousands of sites simultaneously using a botnet.

The attack succeeds when the password is weak, reused, or predictable, and when the site places no limits on how many guesses can be made. Every guess that the server processes also consumes resources, so even unsuccessful attacks can slow a site down.

Common Targets

Brute force attacks aren't limited to website login pages. Common targets include:

  • CMS login pages, such as wp-login.php on WordPress.
  • XML-RPC endpoints, which on WordPress historically allowed many password guesses in a single request.
  • Hosting control panels like cPanel or Plesk.
  • SSH and SFTP on servers with password authentication enabled.
  • Database admin tools like phpMyAdmin exposed to the internet.
  • Email accounts via IMAP, POP3, or SMTP.
  • APIs that accept username and password or API keys.

Types of Brute Force Attacks

"Brute force" is an umbrella term for several related techniques.

  1. Simple brute force: Trying every possible combination of characters. This is only practical against very short passwords, but those still exist.

  2. Dictionary attacks: Trying words from a list, such as common passwords, dictionary words, names, and keyboard patterns like qwerty123. Far more efficient than pure brute force.

  3. Credential stuffing: Using username and password pairs leaked from other breaches. Because many people reuse passwords, a leak from one service can unlock accounts elsewhere. This is often the most successful variant.

  4. Password spraying: Trying a small number of very common passwords against many different accounts. This avoids lockouts that trigger after several failed attempts on a single account.

  5. Hybrid attacks: Combining dictionary words with predictable variations, like Summer2026! or Password1.

  6. Reverse brute force: Starting with a known common password and searching for a username that uses it.

Username Enumeration

Brute force attacks are easier if the attacker knows valid usernames. On WordPress, usernames can sometimes be discovered through author archive URLs, the REST API users endpoint, or login error messages that distinguish between "unknown username" and "incorrect password." Reducing username exposure makes guessing harder, though it's a supporting measure, not a primary defense.

Signs of a Brute Force Attack

Watch for:

  • A high number of failed login attempts in your security plugin or logs.
  • Many requests to wp-login.php or xmlrpc.php from a range of IPs.
  • Account lockout notifications for users who didn't try to log in.
  • Slow site performance with CPU spikes tied to login requests.
  • Alerts from your host about excessive requests.

On a server you manage, you can count requests to the WordPress login page per IP:

sudo grep "POST /wp-login.php" /var/log/nginx/access.log | awk '{print $1}' | sort | uniq -c | sort -rn | head

How to Stop Brute Force Attacks

No single measure is perfect. Layering several makes brute force attacks practically hopeless.

1. Use Strong, Unique Passwords

A long, random, unique password is the foundation. Every additional character increases the number of possible combinations enormously. Use a password manager like Bitwarden, 1Password, or KeePassXC to generate and store passwords of at least 16 characters, or passphrases of several random words.

Most importantly, never reuse passwords. Reuse is what makes credential stuffing work.

2. Enable Two-Factor Authentication

Two-factor authentication (2FA) means a correct password alone isn't enough. Even if an attacker guesses or steals the password, they still need the one-time code from an authenticator app or a hardware key. This single measure neutralizes most brute force and credential stuffing attacks. Plugins like Two Factor, Wordfence, and Solid Security add 2FA to WordPress; a dedicated article on this blog walks through the setup.

3. Limit Login Attempts

WordPress doesn't limit failed logins by default. A plugin can lock out an IP or account after several failures:

  • Limit Login Attempts Reloaded: Lightweight and focused on this one job.
  • Wordfence: Includes brute force protection, lockouts, and a WAF.
  • Solid Security: Offers local and network-wide brute force protection.

A typical configuration allows around three to five attempts, then locks out for 20 minutes, with longer lockouts for repeat offenders.

If you'd rather see how this works in code, here's a simplified example you could add as a small custom plugin. It uses transients to count failures per IP and blocks further attempts for 15 minutes after five failures:

<?php
/**
 * Plugin Name: Sajjad Simple Login Limiter
 * Description: Blocks an IP for 15 minutes after 5 failed login attempts.
 */

defined( 'ABSPATH' ) || exit;

function sajjad_login_limiter_key() {
    $ip = isset( $_SERVER['REMOTE_ADDR'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ) ) : '';
    return 'sajjad_login_fail_' . md5( $ip );
}

add_action( 'wp_login_failed', function () {
    $key      = sajjad_login_limiter_key();
    $attempts = (int) get_transient( $key );
    set_transient( $key, $attempts + 1, 15 * MINUTE_IN_SECONDS );
} );

add_filter( 'authenticate', function ( $user ) {
    if ( (int) get_transient( sajjad_login_limiter_key() ) >= 5 ) {
        return new WP_Error(
            'sajjad_too_many_attempts',
            __( 'Too many failed login attempts. Please try again in 15 minutes.', 'sajjad' )
        );
    }
    return $user;
}, 30 );

add_action( 'wp_login', function () {
    delete_transient( sajjad_login_limiter_key() );
} );

This is intentionally simple. If your site is behind a CDN or proxy, REMOTE_ADDR will be the proxy's IP unless your server is configured to restore the real client IP, so a maintained plugin is usually the better choice for production.

4. Rate Limit at the Server or Edge

Blocking attempts before they reach PHP saves server resources. On Nginx:

# In the http block
limit_req_zone $binary_remote_addr zone=wplogin:10m rate=5r/m;

# In the server block
location = /wp-login.php {
    limit_req zone=wplogin burst=3 nodelay;
    limit_req_status 429;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_pass unix:/run/php/php8.3-fpm.sock;
}

If you use Cloudflare or another CDN, you can create a rate limiting rule for /wp-login.php at the edge so the traffic never reaches your server.

5. Disable or Restrict XML-RPC

If you don't use the WordPress mobile app, Jetpack features that rely on it, or other remote publishing tools, block XML-RPC entirely. On Apache, add this to .htaccess:

<Files "xmlrpc.php">
    Require all denied
</Files>

Or disable it within WordPress, in a small plugin or your child theme's functions.php:

add_filter( 'xmlrpc_enabled', '__return_false' );

The filter disables authenticated XML-RPC methods, but the server-level block is more thorough because requests never reach PHP.

6. Restrict Access to the Login Page

If only a few people log in from fixed locations, you can restrict the login page by IP. On Apache 2.4, in .htaccess:

<Files "wp-login.php">
    Require ip 203.0.113.10
    Require ip 198.51.100.0/24
</Files>

Replace the example addresses with your own. Be careful: if your IP changes, you'll lock yourself out and will need to edit the file over SFTP or your host's file manager. Alternatively, add HTTP basic authentication as a second password prompt in front of wp-login.php.

7. Add a CAPTCHA or Challenge

A CAPTCHA on the login form stops many automated tools. Options include Cloudflare Turnstile, Google reCAPTCHA, and hCaptcha, all of which have WordPress plugins. Turnstile and similar invisible challenges add little friction for real users.

8. Use Fail2Ban on Servers You Manage

On a VPS, Fail2Ban watches log files and bans IPs at the firewall after repeated failures. It's commonly used for SSH but can also watch web logs. A basic SSH jail in /etc/fail2ban/jail.local looks like this:

[sshd]
enabled  = true
port     = ssh
maxretry = 5
findtime = 10m
bantime  = 1h

After editing, restart the service with sudo systemctl restart fail2ban and check status with sudo fail2ban-client status sshd. Make sure your own IP is in ignoreip so you don't ban yourself, and keep an existing SSH session open while testing.

9. Use SSH Keys Instead of Passwords

For server access, disable password authentication entirely and use SSH keys, which are effectively impossible to brute force. In /etc/ssh/sshd_config (or a file in /etc/ssh/sshd_config.d/):

PasswordAuthentication no
KbdInteractiveAuthentication no
PermitRootLogin prohibit-password

Before applying this, confirm that key-based login works in a separate terminal, and keep your current session open. Then validate and reload:

sudo sshd -t && sudo systemctl reload ssh

On RHEL-based systems, the service is named sshd instead of ssh.

10. Avoid Predictable Usernames

Don't use admin, your domain name, or your public display name as your login username. In WordPress, set a different public name in Users > Profile > Display name publicly as, so your username isn't shown on posts.

What to Do If an Attack Succeeds

If you suspect a brute force attack got through:

  1. Change passwords immediately for the affected account and any others using the same password.
  2. Log out all sessions. In WordPress, go to Users > Profile and click "Log Out Everywhere Else," or change the security keys in wp-config.php to invalidate every session.
  3. Check for new admin users and remove any you don't recognize.
  4. Scan for malware and review recently modified files.
  5. Enable 2FA on every privileged account if you hadn't already.

FAQ: Brute Force Attacks

It depends on the password and the defenses. A short or common password can fall within minutes, while a long, random password protected by rate limiting and two-factor authentication is effectively impossible to crack by guessing.

It reduces automated noise because bots often target the default URL, but it isn't a real defense on its own. Combine it with strong passwords, 2FA, and login attempt limits.

Brute force guesses passwords, often from dictionaries. Credential stuffing uses real username and password pairs leaked from other breaches, relying on people reusing passwords across sites.

Occasionally, if someone mistypes a password several times. Sensible thresholds, short lockout periods, and a working password reset flow keep this rare and easy to recover from.

It stops them from succeeding. An attacker may still guess the password, but without the second factor they can't log in. Rate limiting is still useful to reduce server load from the attempts.

If you don't use the WordPress mobile app, Jetpack features that need it, or other remote publishing tools, yes. Blocking it removes a common brute force target.


Conclusion

A brute force attack uses automation to guess logins at scale, whether by trying common passwords, working through dictionaries, spraying popular passwords across many accounts, or replaying credentials leaked elsewhere. These attacks succeed because of weak or reused passwords and unlimited guessing, both of which are easy to fix.

Start with long, unique passwords from a password manager and two-factor authentication on every privileged account. Then add login attempt limits, rate limiting at the server or CDN, a CAPTCHA, and blocks for endpoints you don't use like XML-RPC. On servers you manage, switch SSH to key-only authentication and let Fail2Ban handle repeat offenders. With these layers in place, brute force attempts become little more than noise in your logs.

Tags :
Share :

Related Posts

What are the best WordPress security plugins?

What are the best WordPress security plugins?

The best WordPress security plugins for most sites are Wordfence, Sucuri Security, Solid Security, MalCare, All-In-One Security (AIOS), Patchstack, a

Dive Deeper
What are the most common website security threats?

What are the most common website security threats?

The most common website security threats are vulnerable or outdated software, weak and stolen passwords, malware infections, injection attacks like S

Dive Deeper
How does GDPR affect website security?

How does GDPR affect website security?

GDPR affects website security by turning it from a good habit into a legal obligation. If your website collects personal data from people in the EU (

Dive Deeper