WordPress Brute Force Attack Slowing Your Site: How Thousands of Login Attempts Cause Downtime

Your WordPress site has been getting slower for the past hour. Pages that normally load in under a second are taking five, ten, fifteen seconds. Then they stop loading entirely. Your hosting provider sends a notification: CPU usage at 100%. Your site is down. But nobody changed anything. No updates, no new plugins, no code changes. What happened is an attack — and it does not even need to succeed to destroy your site's performance.

The attack that does not need to break in to break your site

A brute force attack on WordPress is not sophisticated. There is no clever exploit, no zero-day vulnerability, no social engineering. The attacker simply tries to guess your admin password by submitting thousands of username-password combinations to your login page. They run automated scripts that try common passwords, leaked credentials from other breaches, and dictionary word combinations against your wp-login.php page.

Most of these attacks never succeed. Your password is strong enough. The attacker gives up after a few thousand attempts. But here is what site owners do not understand: the attack does not need to guess your password to cause damage. The damage is the attack itself. Every single login attempt forces WordPress to execute its full authentication stack — loading core files, connecting to the database, running the password hash comparison, firing authentication hooks, and logging the attempt. Each one consumes server resources.

One login attempt is nothing. A hundred per minute is manageable. But attackers do not send a hundred. They send thousands. Tens of thousands. From botnets of compromised machines spread across the world. Each attempt ties up a PHP worker, a database connection, and CPU cycles. When all your PHP workers are busy processing login attempts, none are available to serve your homepage, your blog posts, your product pages, or your checkout. Real visitors see timeout errors. Your site is under attack and it is losing the war of resources.

How wp-login.php flooding crashes your server

The wp-login.php file is the default WordPress login page. It is publicly accessible on every WordPress installation at yourdomain.com/wp-login.php. There is no authentication required to access the login form itself — only to submit valid credentials. This means anyone in the world can send POST requests to your login page, and WordPress will process each one.

Here is what happens on each login attempt. WordPress loads the entire core — wp-load.php, wp-config.php, the database connection, the plugin system, and the authentication handlers. It queries the wp_users table to find the submitted username. If the username exists, it retrieves the hashed password and runs it through wp_check_password(), which uses PHP's password_verify() function with bcrypt. Bcrypt is deliberately slow — that is its security feature for protecting passwords, but it also means each failed attempt costs real CPU time.

On a modest shared hosting server, each login attempt takes 200-500 milliseconds of CPU time. That sounds fast, but at 100 attempts per second — which is a moderate attack — your server is spending 20-50 seconds of CPU time every second just processing login attempts. That is more CPU than your entire site needs to serve legitimate traffic. The PHP worker pool is saturated. Nginx or Apache queues incoming requests. Queue fills up. New requests are rejected with 502 or 503 errors. Your site is effectively down.

On shared hosting, the situation is worse because you share resources with other sites. Your hosting provider's resource manager detects your account consuming excessive CPU and may throttle or suspend your account. Now your site is not just slow — it is offline because your host has taken it down to protect other customers on the same server.

xmlrpc.php amplification makes it worse

If wp-login.php brute force is a rifle, xmlrpc.php brute force is a shotgun. The XML-RPC interface was built for remote publishing — allowing tools like the WordPress mobile app and third-party blogging clients to publish posts without using the web interface. It also supports a method called system.multicall that allows multiple XML-RPC method calls in a single HTTP request.

Attackers exploit system.multicall to send hundreds of login attempts in a single POST request. One request to xmlrpc.php can contain 500 or more wp.getUsersBlogscalls, each with a different password. WordPress processes every single one. From the server's perspective, it looks like a single HTTP request, but internally it triggers 500 authentication attempts — 500 database lookups, 500 bcrypt comparisons, 500 times the CPU cost.

This is devastating for performance. A standard brute force attack on wp-login.php at 100 requests per second translates to 100 login attempts per second. The same attack rate against xmlrpc.php with system.multicall translates to 50,000 login attempts per second. Your server cannot process this. It crashes. And because the attack is technically just a few hundred HTTP requests per second — not the thousands that a simple volumetric attack would generate — many basic DDoS protection systems do not flag it.

Refer to the WordPress hardening guide for official recommendations on securing your installation against these attacks.

The performance degradation timeline

A brute force attack does not take your site down instantly. It degrades performance over minutes or hours, and the timeline follows a predictable pattern that monitoring can detect.

Minutes 0-5: Response time creep

The attack begins. PHP workers start processing login attempts alongside legitimate traffic. Your normal 400ms response time climbs to 800ms, then 1.2 seconds. Visitors might not notice yet — pages still load, just slightly slower. Your standard uptime monitor reports everything as up because the site still returns 200.

Minutes 5-15: Worker saturation

Attack volume increases or the initial wave saturates workers. Response time climbs to 3-5 seconds. Visitors notice now. Some leave. Google's crawlers get slow responses and reduce crawl rate. If you have an HTTP monitor tracking response time, this is when you should get your first alert. Intervention at this stage — blocking the attacking IPs at the server or CDN level — prevents the crash.

Minutes 15-30: Queue overflow

All PHP workers are occupied. Incoming requests queue at the web server level. The queue has a finite length. When it fills, the web server starts returning 502 Bad Gateway or 503 Service Unavailable errors. Some requests get through; others do not. The site is effectively in a partial outage — intermittently available depending on whether a PHP worker frees up in time.

Minutes 30+: Full crash

The server runs out of memory, the database connection pool is exhausted, or the hosting provider suspends the account. Every request returns an error. The site is down. Recovery requires blocking the attack source, restarting PHP-FPM and the web server, and potentially contacting the hosting provider to unsuspend the account.

How to harden WordPress against brute force attacks

1. Disable xmlrpc.php

If you do not use XML-RPC — and most modern WordPress sites do not — disable it entirely. Add this to your .htaccess file:

<Files xmlrpc.php>
Order Allow,Deny
Deny from all
</Files>

Or in Nginx, add this to your server block:

location = /xmlrpc.php { deny all; return 403; }

This blocks all access to xmlrpc.php at the web server level, before WordPress even loads. The CPU cost drops to near zero for these requests.

2. Limit login attempts

Install a login limiting plugin that blocks an IP after a set number of failed attempts. After 5 failed attempts, lock the IP out for 15 minutes. After 3 lockouts, lock them out for 24 hours. This does not stop the attack — the attacker can rotate IPs — but it dramatically reduces the number of authentication attempts each IP can make, which reduces the CPU load.

3. Change the login URL

Use a plugin like WPS Hide Login to change wp-login.php to a custom URL that only you know. Automated brute force scripts target the default wp-login.php path. If that path returns a 404, the script moves on to the next target. This is security through obscurity — it should not be your only defence — but it eliminates the vast majority of automated attacks.

4. Add two-factor authentication

Two-factor authentication makes brute force attacks pointless. Even if an attacker guesses your password, they cannot log in without the second factor. Use a plugin that supports TOTP (time-based one-time password) apps like Google Authenticator or Authy. Apply 2FA to all admin, editor, and author accounts — any account that can modify content.

5. Use a CDN or WAF to block at the edge

Services like Cloudflare, Sucuri, and Fastly can block brute force attacks before they reach your server. They identify known attack patterns, block known malicious IPs, and rate limit requests to sensitive URLs. The attack traffic is stopped at the CDN edge, hundreds of miles from your server, consuming none of your server resources. This is the most effective defence because it eliminates the resource consumption entirely.

6. Block login by IP at the server level

If only specific IP addresses need to access wp-admin — your office IP, your home IP, your VPN IP — restrict access at the web server level. In .htaccess:

<Files wp-login.php>
Order Deny,Allow
Deny from all
Allow from 203.0.113.10
</Files>

Replace 203.0.113.10 with your actual IP. This blocks every brute force attempt at the web server level — no PHP execution, no database queries, no CPU cost.

How to detect brute force attacks with Uptrue

Uptrue's HTTP monitoring tracks both uptime and response time on every check. A brute force attack causes a characteristic response time spike that monitoring catches before the site crashes — giving you time to block the attack and prevent downtime.

Step 1: Set up HTTP monitoring with response time alerting

  1. Sign up at uptrue.io/signup (free plan available)
  2. Click Add Monitor from your dashboard
  3. Select HTTP/HTTPS as the monitor type
  4. Enter your homepage URL
  5. Set expected status to 200
  6. Set the check interval to 1 minute
  7. Configure alerts — Slack, email, or Microsoft Teams

Uptrue tracks response time on every check. When a brute force attack begins consuming your server resources, response time climbs from your normal baseline to 2, 5, 10 seconds. The response time history in your dashboard shows the exact moment the degradation started — which correlates with the attack start time in your server logs.

Step 2: Monitor wp-login.php directly

  1. Add another HTTP/HTTPS monitor
  2. Enter https://yourdomain.com/wp-login.php as the URL
  3. Set expected status to 200 (or 403 if you have restricted access)
  4. Set the check interval to 1 minute

If you have blocked wp-login.php at the server level, the expected status should be 403. If the monitor suddenly gets a 200 instead, it means your blocking rule has been bypassed or removed. If you have not blocked it and the monitor gets a 503 or 502, the login page is being overwhelmed — a strong indicator of an active brute force attack.

Step 3: Add keyword monitoring for error pages

  1. Click Add Monitor
  2. Select Keyword as the monitor type
  3. Enter your homepage URL
  4. Set the keyword to "Service Unavailable"
  5. Set the check type to "Page must NOT contain"
  6. Set the interval to 1 minute

When a brute force attack exhausts your PHP workers, some requests get a 503 Service Unavailable page. This keyword monitor catches that error text even if the server returns it with an unexpected status code. Some hosting providers return custom error pages with a 200 status — keyword monitoring catches those.

Step 4: Monitor xmlrpc.php if you cannot disable it

If you need XML-RPC for a mobile app or third-party integration, you cannot disable it entirely. Instead, monitor it:

  1. Add an HTTP/HTTPS monitor for https://yourdomain.com/xmlrpc.php
  2. Expected status: 200 (XML-RPC returns 200 even for error responses)
  3. Set the interval to 1 minute

If xmlrpc.php starts returning 502 or 503, it is under attack. If response time spikes from its normal 200ms to 5+ seconds, an amplification attack is in progress.

Step 5: Set up alerts for maximum speed

  • Slack — instant notification when response time spikes or errors appear
  • Microsoft Teams — keep the development team informed during active attacks
  • Email — written record of attack timeline for post-incident analysis
  • Webhook — trigger automated responses like enabling Cloudflare "Under Attack" mode

Check your WordPress site's attack surface right now

Instant health score across uptime, SSL, DNS, security headers, and performance. See if your login page and xmlrpc.php are exposed.

Check Your Website Score

After the attack: what to check

Check your server logs

Review your web server access logs for the attack period. Look for excessive POST requests to wp-login.php and xmlrpc.php. Identify the attacking IP addresses or ranges. Block them permanently at the server level or in your CDN.

Check for successful logins

If the attack succeeded — if the attacker guessed a valid password — you have a much bigger problem than performance. Check your WordPress user list for new admin accounts. Check your plugin list for newly installed plugins. Check your theme files for modifications. If any account was compromised, change all passwords, revoke all sessions, and scan for malware. Refer to the WordPress site hacked guide for full remediation steps.

Check your database

Some brute force attacks cause database table locks or corruption. Run mysqlcheck --auto-repair on your WordPress database. Check the wp_options table for unexpected changes. Verify that the siteurl and home options have not been modified.

Your site is being attacked right now — the question is whether you know

Every WordPress site on the internet is a target for brute force attacks. This is not a question of if, but of when and how often. Most site owners never see the attacks in their logs because they never look. They only notice when the site slows down or crashes — and then they blame the hosting provider, blame WordPress, blame a plugin. They do not think to check the login page access logs where the real story is written.

Uptrue HTTP monitoring tracks your response time on every check. When an attack starts consuming your resources, the response time graph spikes. You get alerted before the crash. You block the attack. Your site stays up. Your visitors never know anything happened. That is the difference between monitoring and hoping.

Catch brute force attacks before they crash your site

Free plan available. HTTP monitoring with response time tracking. Two-confirmation checks from multiple locations. Slack, Teams, email, and webhook alerts. No credit card required.

Frequently asked questions

How does a brute force attack slow down my WordPress site?

Every login attempt on wp-login.php triggers a full WordPress bootstrap — loading the entire WordPress core, connecting to the database, querying the users table, hashing the attempted password with bcrypt, and comparing it against the stored hash. Each attempt consumes CPU time, memory, database connections, and a PHP worker process. When an attacker sends thousands of attempts per minute, every PHP worker is occupied processing login attempts instead of serving pages to real visitors. The database connection pool fills up. CPU usage hits 100%. Your site either slows to a crawl with response times of 10-30 seconds, or crashes with 502 and 503 errors.

What is xmlrpc.php and why do attackers use it?

xmlrpc.php is a WordPress file that provides an XML-RPC API for remote publishing, pingbacks, and third-party integrations. Attackers exploit it for brute force attacks because it supports the system.multicall method, which allows multiple login attempts in a single HTTP request. An attacker can try 500 username-password combinations in one request to xmlrpc.php, whereas wp-login.php requires a separate request for each attempt. This makes xmlrpc.php attacks far more efficient for the attacker and far more damaging to your server — a single request triggers 500 authentication attempts internally.

Can uptime monitoring detect a brute force attack?

Standard uptime monitoring that only checks for a 200 status code will not detect a brute force attack until it has already crashed your site. But HTTP monitoring that tracks response time will detect it early. A brute force attack causes a gradual increase in response time as PHP workers become occupied with login attempts. Response time might climb from 500ms to 2 seconds, then 5 seconds, then 10 seconds before the site eventually crashes. Monitoring that alerts on response time thresholds catches the attack while your site is still responding — giving you time to intervene before it goes down completely.

How do I stop brute force attacks on WordPress?

Layer multiple defences. First, block direct access to xmlrpc.php in your web server configuration or .htaccess — most WordPress sites do not need it. Second, limit login attempts using a plugin like Limit Login Attempts Reloaded or Wordfence. Third, change the login URL from wp-login.php to a custom URL using a plugin like WPS Hide Login. Fourth, add two-factor authentication to all admin and editor accounts. Fifth, use a Web Application Firewall (WAF) like Cloudflare or Sucuri that blocks known attack IPs at the edge before requests reach your server. Sixth, block access to wp-login.php by IP at the server level if only specific IPs need admin access.