What is User Enumeration?

WordPress websites may reveal whether a username exists on system through the author query variable. When a web app leaks information about whether a username exists or doesn’t exist, this is called user enumeration. A common example is when you see a validation notice telling you that the username is already in use, or that the provided password is wrong (instead of the username OR password). More information can be found at OWASP.

How to Stop User Enumeration in WordPress

There are a few ways to do this, basically we want to remove the ability for bots, or users, to visit our block and request an author archive page. If you’ve noticed a large number of requests to /?author=X in your logs, then you’re being hit by bots trying to do this. Here are a few approaches I’ve used, or would suggest, to combat this.

Option #1: In your Theme’s functions.php

The universal approach involves adding a small bit of code to your WordPress theme or plugin in order to re-direct malicious requests that attempt to enumerate users. Here’s a function I commonly use to do this:

/**
 * Block User Enumeration
 */
function kl_block_user_enumeration_attempts() {
    if ( is_admin() ) return;

    $author_by_id = ( isset( $_REQUEST['author'] ) && is_numeric( $_REQUEST['author'] ) );

    if ( $author_by_id ) 
        wp_die( 'Author archives have been disabled.' );
}
add_action( 'template_redirect', 'kl_block_user_enumeration_attempts' );

Option #2: .htaccess Rules for Apache Servers

If your WordPress site is run on a server with Apache, then you can add the following rule to the .htaccess file in your installations root folder.

# Block Attempts to Enumerate WordPress Users
RewriteCond %{REQUEST_URI} !^/wp-admin [NC]
RewriteCond %{QUERY_STRING} author=\d
RewriteRule .* - [R=403,L]

MOST of the other htaccess approaches our there use a 301 redirect, but I suggest sending them to a 403 Forbidden response as suggested by WASP standards.

Option #3: Config Rules for nginx Servers

If your WordPress website is powered by nginx, then the following rule can be added to the location / { ... } block of your WordPress sites’ *.conf file to send these requests to a 403 Forbidden error page, which seems appropriate.

# Block user enumeration
if ( $query_string ~ "author=([0-9]*)" ) { return 403; }

The full location block would then look something like this:

location / {
    index index.php;
    try_files $uri $uri/ /index.php?$args;

    # Block user enumeration
    if ( $query_string ~ "author=([0-9]*)" ) { return 403; }
}

That should do it, using any of the above method you should stop those nasty user enumeration bots in their tracks. As always, if you have any questions let me know!

About the Author

Kevin Leary is a web developer in Boston, MA specializing in enterprise website design and development, online marketing, and conversion optimization.