Recently I have been doing a lot of testing on a couple of my web sites that run WordPress and realized that securing your site takes a bit of effort. There are some plugins that do a great job at certain things however I wasn’t able to find any that did a great job of securing everything that I would prefer be secured. Below I describe a multi-pronged approach to securing your WordPress site from hacking attempts using multiple WordPress plugins as well as performing a couple manual steps that ensure the WordPress details exposed to the world are minimal.

UPDATE: :: 07-25-2012 ::

While talking about WordPress with my boy Louis(@hacktalkblog) at BlackHat 2012 tonight we were discussing the user enumeration issue. He had on his list to write a patch for the user enumeration issue so we got together to put it together and post it. Turns out he was talking about a user enumeration issue I was not familiar with located in /wp-admin sub directory while I was talking about the one below. The issue Louis pointed out to me occurs via the wp-login.php page where it will provide different errors based on if you have the right username and the wrong password or if you have the wrong username. Below is a downloadable patch that blocks both forms of user enumeration. Thanks Louis @ hacktalk.net!

WP User Enumeration Blocking Patch: Download

Why Secure WordPress?, What Should Be Secured On My WordPress Site?

Both of the above are great questions and definitely would not be obvious to someone not working in the Information Security field. A default WordPress site with some plugins installed is a gaping hole to the world that opens the door for disaster down the road. Because WordPress is so popular there are vulnerabilities that come out on a regular basis and it is rather surprising how some don’t get fixed in the base code though some people may view some of the vulnerabilities as minor issue I personally consider them major. One of the vulnerabilities that came out back in May of 2011 is rarely discussed on the web outside of Information Security professionals and to me is something that should be blocked immediately. The particular vulnerability that I am talking about is “WordPress User IDs and User Names Disclosure” or “WordPress Login Enumeration”. You might say who cares if someone knows what my login is since they do not know the password, but the truth is knowing the login is more than half the battle. Once a hacker has the login to your WordPress site they can begin brute forcing the login and no matter if it takes one hour or a month if they are determined enough they will gain access to your WordPress admin. The other issue at hand is the fact that many people either change the name of the admin user, which by default is user-id 1, or they create other users with full privileges in the WordPress admin that are named something obvious like super_user. Once these names are enumerated from the database an attacker will focus on the usernames they believe to have the highest privileges. The more information an attacker or hacker has about your WordPress site and the server that the WP site is running on the more likely they will be able to gain access. If you are not yet convinced that you should do what you can to minimize the exposure of your WordPress site then you can stop reading now, but if you have come to the conclusion that you would like to tighten things down and make it harder for people to destroy what you have worked for then continue on below. I provide numerous suggestions for how you can secure your WordPress web site.

Block WordPress Login Enumeration, Fix WordPress User IDs and User Names Disclosure:

This first security fix is the one I am really surprised is not in any security plugins that I checked out. It is definitely possible that the changes I recommend below break something else on your WordPress site however I have been testing this and been unable to find any issues caused by the recommended changes. So the issue at hand is the fact that you can query a specific URL structure on WordPress and you will only get a response when you have guessed the user id and you will be redirected to a username also known as authors. The problem with this is the fact that WordPress does not differentiate between WordPress authors and WordPress admins. The below examples describe the vulnerability step by step through the process.

How To Enumerate WordPress Login ID’s And Usernames:

Open the following URL but change the domain to the domain running your WordPress site:

URL: http://www.wordpressexample.com/?author=1

If you have not deleted the default admin user created during your WordPress install you will be redirected to a URL similar to the following:

URL: http://www.wordpressexample.com/authors/admin

So as you can see you now know that the default admin user still exists, it’s user id is 1, and the login is actually the default of admin. Now if you received an error such as a 404 indicating that this user does not exist you could move right along to the next URL such as the following:

URL: http://www.wordpressexample.com/?author=2

If the above URL is successful in being redirected to something that means you will now know another user id and user name. It would obviously be easy to write a script that would walk through thousands of user ids in a short amount of time and in the end you would know all of the WordPress user id’s that are active and their corresponding WordPress logins.

How To Defend Against WordPress User ID And Login Enumeration:

Again this fix was created by me and I am not sure if anyone else has done this or if there are any hidden problems I am causing though for me it is worth the risk as I can easily troubleshoot problems if they arise. It would however take me much longer to have to restore my entire site from scratch if it were hacked and defaced or destroyed. To block user login enumeration we are going to add a couple lines to the .htaccess file located in the root web directory of your WordPress web site as shown below. You will want to add this near the top of the .htaccess file because of it is added below the normal redirect it is useless.

Code To Add To .htaccess File To Block WordPress User Enumeration:

RewriteCond %{REQUEST_URI}  ^/$
RewriteCond %{QUERY_STRING} ^/?author=([0-9]*)
RewriteRule ^(.*)$ http://www.wordpressexample.com/some-real-dir/ [L,R=301]

The code above says that any request made to the WordPress site that matches the query string of “/?author=should be redirected to http://www.wordpressexample.com/some-real-dir/. I have this code right under “ServerSignature Off” which is at the top of the .htaccess file in the WordPress root directory. Once you add these couple lines to the .htaccess file user enumeration is now blocked. Continue below for other security measures to take with your WordPress site.

Minimize WordPress Data Available Such As Block WordPress Version From Displaying:

To accomplish the goal of minimizing WordPress information that is exposed I install a WordPress plugin called Secure WordPress. A quick search for Secure WordPress on the WordPress plugins site should return the Secure WordPress plugin at the top of the results. Just by installing and activating Secure WordPress you will resolve numerous security holes including allowing attackers to see your WordPress version, provides some protection against malicious URL requests, and removes the Really Simple Discovery link in wp_head. I also like to enable every other check box except for the Error Messages check box, so a one option that is not checked by default but I do check is Windows Live Writer. I would also suggest signing up for WebSiteDefender as you will get a free scan of your web site and can be accomplished via the Secure WordPress settings page.

Block Various SQL Injection Attempts To WordPress & Secure Other WP Areas:

Another plugin I install is called BulletProof Security also available on the WordPress site in the plugins directory. The WordPress plugin BulletProof Security is a bit more complex as you will first generate .htaccess files for various locations on your WordPress site and then be required to merge them into existing .htaccess files. Make sure that when you merge the changes that the redirect for author that we previously added stays near the top of the .htaccess file located in the WordPress root directory. BulletProof Security provides a bunch of rules that minimize your exposure to SQL Injection and other nasty attacks.

Remove readme.html File In WordPress Root Directory:

This one is self explanatory. During the installation of WordPress a readme.html file is generated in the root WordPress directory so make sure to remove it. You can remove this file via FTP or using “rm” from the command line.

Other WordPress Security Plugins To Consider:

Depending on the WordPress installation I also install a couple other plugins related to security including the Login Lockdown WordPress plugin, the AntiVirus WordPress plugin, the Login Logger WordPress plugin, and The WP Block Admin WordPress plugin. You should also consider something like Really Simple Captcha and make sure to include a Captcha on any contact form installed on your site which will also cut down on SPAM.

Last but not least make sure permissions are correct through out the entire WordPress directory. If you provide the incorrect write permissions to the wrong files you are guaranteed to be hacked in a short amount of time.


Kindle Edition: Check Amazon for Pricing Digital Only

WordPress 3 Ultimate Security (Paperback)

By (author): Olly Connelly


List Price: $49.99 USD
New From: $44.99 USD In Stock
Used from: $40.99 USD In Stock

DeliciousStumbleUponDiggTwitterFacebookRedditLinkedInEmail
Tags: , , , , , , , , , , , , , , , , ,
5 Responses to “Block WordPress User Enumeration, Secure WordPress Against Hacking”
  1. Andy says:

    Nice article… should the Redirected URL not have a “?” on then end.

    If I use your version it does the redirect, but appends the “QUERY_STRING” to the end.. so it comes out as “www.wordpressexample.com/some-real-dir/?author=10″

    This works for me :
    RewriteRule ^(.*)$ http://www.wordpressexample.com/some-real-dir/? [L,R=301]

    [Reply]

    alex Reply:

    Hello Andy,

    That is definitely a valid point… it would depend on what the end goal was and if you wanted to say track how many hits were going to specific URL’s so the query was still making it into your web analytics. If it is more important to avoid a 404 or something then your method would be the proper way but if you were less worried about the 404 errors to end users on those pages and more interested in tracking if users visit every author id then the method in the article would be best. In my case I am interested in tracking when people attempt to enumerate account data by hitting every author ID as I not only log when X number of author pages are visited in the same 10 minutes but I also send a notification in case further action needs to be taken to protect my sites.

    Regardless I can see where more people would prefer your method so thanks for taking the time to explain/share in detail!

    Thanks.
    alex

    [Reply]

  2. Joe says:

    I think Andy’s point is that the rewrite rule, as written in the blog post, does not effectively prevent the username enumeration. If the goal of the attacker is to identify usernames to aid in an attack, the rewrite rule you show does not stop the usernames from being disclosed, because the query string with the username is appended to the rewritten URL and still returned to the caller. So, to the point of the topic of the article (blocking wordpress user enumeration), it’s not an effective fix.

    I agree with Andy that adding a ‘?’ to the end of the rewritten URL effectively blocks the enumeration (at least for this attack path).

    Great blog post, by the way — I appreciate the information a great deal.

    [Reply]

  3. Alan says:

    This doesn’t need a patch or htaccess to stop user enumeration, a simple filter will do the job.

    To help less technical people I have put the filter in a plugin here http://wordpress.org/plugins/stop-user-enumeration/

    [Reply]

  4. WebMasta says:

    As an alternative rewrite-role use the following, it will internally redirect to user 99999 which should not exist and so a 404 is returned for all author requests. With this the attacker does not even know if an user-id exists at all.

    RewriteCond %{REQUEST_URI} ^/$
    RewriteCond %{QUERY_STRING} ^/?author=([0-9]*)
    RewriteRule ^(.*)$ $1?author=99999 [L]

    [Reply]

  5.  
Leave a Reply

*Type the letter/number combination in the abvoe field before clicking submit.

*