Oct 272013
 

This is a really simple fix which will block the user enumeration on a wordpress site (like the method by wpscan).

Before I get into this, I am very well aware of the IfIsEvil page on nginx wiki.  But it also says on this page, “The only 100% safe things which may be done inside if in location context are:  return and rewrite as the last statement in a location block”  With that in mind, we are going to use ONLY rewrite as the last statement in our location block.

First some examples of using wpscan to enumerate users.

If I wanted to see the default first 10 users of a wordpress site, I would simply enter:

wpscan --url http://my.url.com --enumerate u

i.e.

wpscan --url www.edwiget.name --enumerate u
 
<snip> ....
 
[+] We found the following 10 user/s :
    +----+----------------------+----------------------+
    | Id | Login                | Name                 |
    +----+----------------------+----------------------+
    | 1  | admin                | admin                |
    | 2  | user2                | user2                |
    | 3  | user3                | user3                |
    | 4  | user4                | user4                |
    | 5  | user5                | user5                |
    | 6  | user6                | user6                |
    | 7  | user7                | user7                |
    | 8  | user8                | user8                |
    | 9  | user9                | user9                |
    | 10 | user10               | user10               |
    +----+----------------------+----------------------+

How does wpscan determine the users on a wordpress site?  We can tell from a tcpdump that it simply adds “?author=[1-10]” to the requested domain.

enumerate-users

So basically, on an unprotected site you can do the same if you simply add /?author=1 to any wordpress site.  The first user is always the admin.  Having the admin name or any user names would make brute forcing wordpress logins easier.  BTW, if you follow my articles, you know brute forcing users is stopped by protecting the wp-admin url using this article. Also, you can determine by simply incrementing the number until you get an error to determine how many users are registered on a site.  This might be useful to determine a sites popularity.  I will note that there are other ways to get user names from a wordpress site….such as from comments.

Either way, I wanted to stop user enumeration using the ?author= method on an nginx site.  This was done by simply adding:

if ($args ~ "^/?author=([0-9]*)"){
        set $rule_0 1$rule_0;
}
 
if ($rule_0 = "1"){
        rewrite ^/$ http://edwiget.name/404 permanent;
}

To the end of my “location / {” statement right before the ending “}” so now it looks like this:

server {
   listen 80;
   server_name domain.com www.domain.com;
   access_log /logs/domain.com-access.log;
   error_log /logs/domain.com-error.log;
   root /var/www/sites/domain.com/htdocs;
location / {
try_files $uri $uri/ /index.php?q=$request_uri;
	   }
include /usr/nginx/conf/staticfiles.conf;
include /usr/nginx/conf/php.conf;
include /usr/nginx/conf/drop.conf;
 
        # password protect wp-admin
                location ~ ^/wp-admin {
                auth_basic “Restricted”;
                auth_basic_user_file /path/to/htpasswd/file;
                try_files $uri $uri/ /index.php?q=$request_uri;
                }
 
	if ($args ~ "^/?author=([0-9]*)"){
        set $rule_0 1$rule_0;
	}
 
	if ($rule_0 = "1"){
        rewrite ^/$ http://domain.com/404 permanent;
	}
}

Reload nginx and try to enumerate users again.

# wpscan --url www.edwiget.name --enumerate u
 
<snip> ...
 
[+] Enumerating usernames ...
We did not enumerate any usernames :(

 

  One Response to “Blocking wordpress user enumeration on nginx”

  1. blogging Thanks for the helpful post! I would never have discovered this on my own!

    Thanks for the helpful post! I would never have discovered this on my own!