Wordpress - Can I Prevent Enumeration of Usernames?
A simple solution I use in a .htaccess
:
RewriteCond %{REQUEST_URI} !^/wp-admin [NC]
RewriteCond %{QUERY_STRING} author=\d
RewriteRule ^ - [L,R=403]
It is similar to @jptsetme’s answer, but it works even when the query string is /?dummy&author=5
, and the search pattern for RewriteRule
is very fast: You often see a capture ([0-9]*)
in regular expressions for this. But there is no need to waste memory for the capture when you don't use the captured expression, and a match for the first character is enough, because you don't want to accept author=1b
.
Update 20.04.2017
I'm seeing more "broken" requests from people who are even too stupid to run a simple scan. The requested URLs look like this:
/?author={num:2}
So you could extend the rule above to:
RewriteCond %{REQUEST_URI} !^/wp-admin [NC]
RewriteCond %{QUERY_STRING} ^author=\d+ [NC,OR]
RewriteCond %{QUERY_STRING} ^author=\{num
RewriteRule ^ - [L,R=403]
You can't.
The WPScan tool is an automated utility that takes advantage of WordPress' friendly URLs to determine usernames. It will loop through the first 10 possible IDs for authors and check the Location
header on the HTTP response to find a username.
Using http://mysite.url
for example ...
WPScan will check http://mysite.url/?author=1
. If your site is using pretty permalinks, it will return a 301 redirect with a Location
header of http://mysite.url/author/username
. If your site isn't using pretty permalinks, it will return a status of 200 (OK) instead, so WPScan will check the feed for the string "posts by username" and extract the username.
What you can do
First of all, just because someone can guess your username, doesn't mean your site is insecure. And there is really no way you can prevent someone from parsing your site in such a way.
However ...
If you are really concerned about this, I would recommend doing two things:
- Turn off pretty permalinks. This will force WPScan and similar tools to parse the content of your site for usernames rather than relying on the URL.
- Force users to set a different nickname. In the absence of a username in the URL, scanning tools will search for "posts by username" in the feed/post content instead. If you aren't putting usernames out there, then they can't be nabbed.
Another alternative is to change your author permalink rewrites. There are several ways you can do this, and you can probably find a few on this site as well.
Not tested this out thoroughly, but I think it's preferable to remove underlying resource rather than try to build walls around it on web server level. So in WP terms that would be stopping it from processing author-related query variables.
if ( ! is_admin() ) {
add_filter(
'query_vars',
function ( $public_query_vars ) {
foreach ( array( 'author', 'author_name' ) as $var ) {
$key = array_search( $var, $public_query_vars );
if ( false !== $key ) {
unset( $public_query_vars[$key] );
}
}
return $public_query_vars;
}
);
}
PS note that this will kill author archives entirely, which might or might not be appropriate paranoia level :)