
After evaluating hundreds of websites, we can say that rare are the sites that have totally blocked the feature.

After evaluating hundreds of websites, we can say that rare are the sites that have totally blocked the feature.
1. HTTP parameter “rest_route”
The first bypass we are presenting is abusing an alternative path to reach the same endpoint. While Worpdress is configured – by default – to support URL rewriting to have search engine and human friendly URLs like https://website.com/2020/12/breaking-news
instead of https://website.com/?p=2678
, behind the scene, every request sent to /wp-json/ is entering the index page with the parameter “rest_route” set to /wp/v2/users.
https://****.com/blog/wp-json/wp/v2/users | BLOCKED |
https://****.com/blog/?rest_route=/wp/v2/users | OK |
2. WordPress.com API
https://blog.*******.com/wp-json/wp/v2/users | BLOCKED |
https://public-api.wordpress.com/rest/v1.1/sites/blog.*******.com/posts | OK |
3. One by one
add_filter( 'rest_endpoints', function( $endpoints ){
if ( isset( $endpoints['/wp/v2/users'] ) ) {
unset( $endpoints['/wp/v2/users'] );
} return $endpoints;
});
In the table below, we can see that one host was refusing to serve the complete list of users. However, we realize that targeting a specific user was not being blocked.
https://www.*****.org/wp-json/wp/v2/users | BLOCKED |
https://www.*****.org/wp-json/wp/v2/users/1 | OK |
4. Case sensitivity
foreach ( $routes as $route => $handlers ) {
$match = preg_match( '@^' . $route . '$@i', $path, $matches );
if ( ! $match ) {
continue;
}
$args = array();
Source: class-wp-rest-server.php
RewriteCond %{QUERY_STRING} \bwp/v2/users\b [NC]
RewriteRule ^ - [F]
RewriteCond %{QUERY_STRING} \bwp/v2/users\b
https://blog.*****.com/section/news?rest_route=/wp/v2/users | BLOCKED |
https://blog.*****.com/section/news?rest_route=/wp/v2/usErs | OK |
5. Search
On few occasions we encounter APIs that are not explicitly blocked but the /wp/v2/users endpoint is not returning the avatar_urls properties. This is the effect of a third-party security plugin or disabling manually the avatars (Settings > Discussion > Avatars).

https://api.*****.com/wp-json/wp/v2/users | BLOCKED |
https://api.*****.com/wp-json/wp/v2/users?search=r@initech.com https://api.*****.com/wp-json/wp/v2/users?search=er@initech.com https://api.*****.com/wp-json/wp/v2/users?search=ter@initech.com https://api.*****.com/wp-json/wp/v2/users?search=eter@initech.com https://api.*****.com/wp-json/wp/v2/users?search=peter@initech.com |
OK |
6. Yoast SEO
<script type='application/ld+json' class='yoast-schema-graph yoast-schema-graph--main'>{"@context":"https://schema.org","@graph":[{"@type":"WebSite","@id":"https:// ***** /#website","url":"https://www.******.com/","name":"*****",
[...]
},
{
"@type":["Person"],
"@id":"https://www.****.com/#/schema/person/7367999b66**********",
"name":"Fred",
"image":{
"@type":"ImageObject",
"@id":"https://www.******.com/#authorlogo",
"url":"https://secure.gravatar.com/avatar/de04459893a29***********?s=96&d=mm&r=g",
"caption":"****"
},
"sameAs":[]
}]
</script>
Conclusion
Clients of GoSecure Managed Detection and Response (MDR) with the Network Detection and Response have detection capabilities in-place in case of WordPress user enumeration and other malicious requests sent to WordPress.