Wordfence Blocks Username Harvesting via the New REST API in WP 4.7

WordPress 4.7 was released 6 days ago, on December 6th. It includes a REST API that will be used by many WordPress plugins, mobile apps, desktop applications, cloud services and even WordPress core in future. Every site that upgrades to WordPress 4.7 has this API enabled by default.

The API is powerful and allows WordPress to move from being a simple web based content-management system into being an application framework. What this means is that developers can write applications that run anywhere and talk to your WordPress website. So in future you’ll be able to publish content and manage your site from the cloud, from your phone, tablet or desktop and plugin developers will be able to create new kinds of extensions that improve your WordPress experience. All of these applications will use the new WordPress REST API that was released in WordPress core version 4.7.

As the saying goes, with great power comes great responsibility. Parts of this new API are available to anyone on the internet. They don’t need to sign into your WordPress website to use the API. They can just connect and use it. With the launch of this API, we expect developers to embrace it, but we also expect hackers to find ways to exploit it.

WordPress REST API Threats

The new WordPress REST API allows anonymous access. One of the functions that it provides is that anyone can list the users on a WordPress website without registering or having an account.

This can be exploited by bots that are launching brute-force password guessing attacks on WordPress websites. They can use this API to list the usernames of anyone who has published a post on a WordPress site. The list of users displayed via this API almost always includes a user with admin level access.

To see this WP REST API function in action, simply visit a site with WordPress 4.7 installed and hit the URL: example.com/wp-json/wp/v2/users

This will list all users that have published a post. It includes that user’s userid, username, gravatar hash and website URL. We are seeing well known brand name websites that have now upgraded to WordPress 4.7, where we are able to enumerate all usernames who have published posts, simply by visiting the above URL.

Wordfence already includes protection that makes it more challenging for bots to discover your admin username. This morning’s release updates this feature to extend this protection to the new WordPress 4.7 REST API.

Fine granularity: Keeping the bad guys out and letting the good guys in

Instead of providing an option to disable the entire REST JSON API, which some security vendors have done, we recognize how powerful and useful this new application programming interface is. We expect it to be widely embraced and to significantly enhance the power of WordPress.

To mitigate this threat, we have targeted the specific functionality in the API that exposes usernames. If you enable the feature (described below) it will simply stop anonymous users from being able to retrieve a list of users and their usernames. We don’t disable or break any JSON API functionality. Authenticated users using the API will be able to list their own user information. Authenticated users with list_users permission will be able to list all users.

We have made the REST API team aware of the new protection we have added on WordPress Slack and have received some helpful input. We will continue working with them and other developers to ensure that Wordfence enhances the security of WordPress and the new REST API, while ensuring compatibility with all applications.

How to enable protection against user enumeration

Wordfence 6.2.8 was released this morning and includes protection against attackers enumerating usernames using the new WordPress 4.7 JSON API. This option is enabled by default. To verify that this option is enabled, or to modify the setting, you can find it on your Wordfence options page with the label:

“Prevent discovery of usernames through ‘/?author=N’ scans, the oEmbed API, and the WordPress REST API”

You can find that option under the “Login Security Options” heading on the Wordfence options page.

This option is available to all Wordfence users, both free and paid.

You can find the documentation for this option on docs.wordfence.com.

We’d like to hear from you

We’d like to hear from any WP developers who are using this API and have any questions. We aren’t aware of any applications currently that rely on making unauthenticated requests to WordPress 4.7 to get a list of users. If you’re aware of any plugins or other applications that rely on the anonymous enumeration of users, and that are affected by this change, please post in our comments and we will modify our documentation.

As always I’ll be around to answer any questions from the community in our comments.

Special thanks to our team and especially Ryan Britton and Matt Rusnak for working hard to develop and test this feature in time for a Monday morning release.

Mark Maunder – Wordfence Founder/CEO.

Did you enjoy this post? Share it!

Comments

63 Comments
  • You guys are ROCKSTARS! I can't imagine a WordPress world without WordFence. However, it leaves WordPress in serious question.

    Thank you so very much for all you do and all your hard work! You're a stellar company with stellar service! Absolutely, without question, the very best!!!

    • There's only 1 reason why I don't take the time to invest time in learning Joomla or Drupal.

      I haven't heard that there is a Wordfence plugin for them yet.

      That plus I looked at them once and I don't have experience in much scripting and joomla and drupal confused the hell out of me and they don't have a lot of plugins. Course if your code isn't barphing and bleeding security leaks all the time you don't need as many plugins.

  • I was wondering why this aspect wasn't stressed by anyone, when WP 4.7 came out last week. On the installs I've upgraded to 4.7 until now, I used this plugin to block the API: https://wordpress.org/plugins/disable-json-api/

    Besides security aspects, you might just have an intranet-like WP-install, where you don't want to suddenly expose content.

    Of course it's up to a responsible site administrator to study and test how upgrades affect a particular install, but these aspects could have been stressed more.

    Thanks for including this in WordFence!

  • THANK YOU!!! Wordfence is a mandatory plugin for all the websites we host - and THIS is why. I can not believe this hole in security is built into Wordpress. We go through great lengths to hide usernames... and then they do something like this.... unreal.

    Thank you Wordfence!

  • Thanks for this, can you show us a website were we can see this happening?

  • Just installed this awesome plugin. We run a Wordpress site for our business selling software for the retail floral industry (florist websites and point of sale).

    We are now using WordFence for our Wordpress website. Seriously good work (and shocking that the Wordpress team would leave such a huge security hole in an application used by hundreds of millions of people).

  • wordfence, you are the best!!!

    I just followed your instructions: example.com/wp-json/wp/v2/users
    I all my users were reveled. this is a major hazard.
    updated wordfence and the API is blocked :)

    wordpress developers should seriously do an reevaluation of themselves.

    thank you so much wordfence

    • Just to note: only users who have published a public post (i.e. post authors) are exposed via this endpoint, and all data exposed via the API is already available by default in WordPress.

      (See my longer answer below for more detail.)

  • Does this bypass the Change user_nicename tip?

  • Thank you for this. I just did not believe to see our users listed so clearly for everyone to see. I updated immediately and Re-run the URL. I got: "Sorry, you are not allowed to list user". Just perfect! GREAT JOB.

  • Great work, and thank you!

  • Thanks for this new option, I don´t use the API now but I could see that the URL efectively show all users, I have clients that depend of the website, and after the update and check the new option, this action doesn't happen more.

    Thanks guys!

  • Thanks for the heads up.

    I use 2FA on my company sites, but am seriously thinking of having Nginx block access to this URL.

    Cheers,

    Jeremy

    • I may do the same although the damage is done. Bots can scrape a lot of user names since wordpress released this version. True, many bad guys probably did not know about this but I'm sure some found out quickly.

      • I am sure some have grabbed the usernames. You shouldn't think for a second these can really be protected and deploy other means like 2FA and max attempts failed banning. Items like Failban, at the server level, help too.

        Still it never hurts to block access to these kinds of APIs unless you need it. All security is best done in layers. So running Wordfence is great along with using Nginx (or Apache) to block access at the web server level.

        IMO I think API should be optin/allow whitelist NOT optout/allow world.

        Cheers,

        Jeremy

  • Whoa, This gets me thinking about how many valid usernames will now be found to bruteforce.

    Although your plugin alleviates this issue, as it is good practice in a desktop environment, Would it be good practice to have two WordPress users setup, one as admin and another "dummy" one to publish?

    • Neil, your username should never show publicly, but you don't need to create a dummy user to accomplish this. If you go into your user profile in the WordPress Dashboard, you will see a field for "nickname." This is what the public sees when you post, and it should always be different from the username you use to log in to WordPress. For people with business sites where their name is a part of their brand identity which they want to be visible, they should use their name as the nickname, NOT as their username. Your username (login name) should not be anything that can be found anywhere on your website.

      • I changed my username to be different from my public display name. But if you hover your mouse over the public display name, my username shows up as part of the "author" URL. Can't the hackers get it that way?

  • For those of us starting small businesses, with limited knowledge, your speed, ease and clarity of response to issues I'd never have spotted is very comforting. Thank you. When my business grows, I'll certainly be upgrading to pay for your premium services.

  • Thanks Mark, as always, Wordfence has our back - I really appreciate this!

  • Awesome patch.

    Quick question to the Wordfence team: What's your favorite, or what do you think is the most useful aspect of using REST API for WordPress?

    • We haven't integrated with it yet, but I expect mobile applications to manage your WP site or that provide WP functionality will be the most exiting field of development.

      Mark.

  • Thank you for adding a helpful feature.

    User info should never be public.

    I restricted REST API access by IP on my sites.

    Best wishes,
    Mitchell

  • Thank you for the timely information.

  • Thanks for the heads up on this. An outstanding job and fast response. I have to say, I am disappointed in Wordpress for not giving Admins the ability to turn the API off and for having it on where any anonymous user can retrieve user names. Thanks for your hard work and for making Wordfence free. You guys and gals are the best.

  • Yikes! It's hard enough to get my clients to use even moderately secure login credentials. We really need WordPress to be working WITH us on security, not punching new holes in it. Good catch, and MANY thanks for getting a fix out so swiftly!

  • Just curious, when do you recommend we upgrade to a new Wordpress Major Release? Do you recommend we wait a certain period of time, like a few days? Kind of seems like upgrading to a Major Release right away could pose a security risk.

    Thanks
    Clint

    • We usually read the changelog and if there are potentially breaking changes we'll wait a few days. Also for every release of this website we have a staging environment where we can test new releases before upgrading the production site. This site is still not upgraded to 4.7. We'll probably do that this week some time.

      Security releases for WP core are different though. You'll want to update as soon as possible if it's any kind of security release. The reason is because as soon as the release goes out, the vulnerabilities become public. So they will be exploited quite quickly and you want to shrink that window of exploitation as much as you can by upgrading sooner.

      Mark.

  • He guys,

    Correct me if I am wrong but the method does NOT scrape the usernames but only the required Nickname...

    Example profile:

    Username: Bas
    Nickname (required): Jelle
    Display Name: Jelle

    Then example.com/wp-json/wp/v2/users will show " Jelle" and NOT "Bas"

    So in this case their would not be a problem I suppose (besides the gravatar issue)

    So if you if you fill in your username

  • Hey Marc,

    I know the free version gets the updates like at the end of the week and the paid version gets same day. Something like this is it already included in the free version or in a few days?

    • Hi Brad,

      This is available in Wordfence free and paid immediately. What you're thinking of is our threat defense feed, which contains our malware scan signatures and firewall rules. Our Premium customers get those in real-time. Our free customers get those with a 30 day delay. But when we add a new feature like this, it's available immediately.

      Mark.

  • I just updated WordPress on my websites, but I only updated WordFence on one of them. When I ran the URL to see if I could access the usernames, it didn't display. But on the site I didn't update with WordFence, there it was.

    Very disturbing.

    If you have comments enabled on your website, anyone can easily find your username in the source data, whether your post a comment or not. Does WordFence address this vulnerability?

    • No we don't. This really depends on your theme and it's harder for bots to find your username if they need to parse a theme, which varies from site to site. If they get to use an API, it's super easy.

      Mark.

  • You guys are ROCKSTARS! Keep up the good work keeping us safe!

  • What do you mean by "breaking changes"?

    What time frame before upgrading to a Major Release, do you recommend for someone who may have a hard time gauging a "breaking change"?

    I am also curious, what is the "production site" you reference?
    Thanks again

    • Oh boy I feel like I've opened a can of worms here. What I meant is changes that may break our own site. For example, a new feature in WP core that could affect the way our site works.

      If you aren't a developer it's difficult to know if a feature in WP will affect the function of your site. It almost never does, but we're very careful because we run a very high traffic production website.

      The production website I was referencing is our own site at www.wordfence.com. We also have a staging website that we use for testing and we have various developer websites. They are all copies of this site and we use them as part of our workflow to develop and test changes we're implementing on our main www.wordfence.com site. That's just the way we work. Wordfence is a reasonably large dev team along with QA, a bug tracking system, source repositories and all the other bits and pieces that go with being a busy software company. So we tend to use formal software dev and QA methodologies rather than the usual WordPress workflow.

      So I think by describing some of our workflow I may have created more confusion than anything else. Most WP users don't have a staging environment and they'll just do an in-place upgrade to a new version of WordPress core. And most of the time - in fact almost always - it will go quite smoothly.

      I hope that helps clarify things.

      Mark.

  • Hi,
    Names are still displaying for me after following your instructions.

    • Are you looking at a cached page John?

  • You are the best! But Pro plugin high price in Turkey! Make it new gate way in Turkey via Turkish liras!

  • So glad you guys are on top of this. That was a fundamental change in WP that was not well documented.

  • Absolutely priceless post, thank you guys.

  • Nothing new exposed. What is exposed us the user slug (internally: user_nicename). This does not need to be the username. I have been using the plugin "WP Author Slug" by Obenland for a while. This ensures the user slug is derived from the display name, not the username. Then attackers may enumerate as much they like, either by the classic /author/ page or by the new /wp-json/ API without getting any login id.

  • I had not looked at this possibility and am amazed that WordPrss would have left the door open. Thank you Mark for having our backs.

  • Excellent! You guys rock!

  • Once again, Wordfence to the rescue!!
    Hope they pay you guys for finding flaws in their own updates, come on now.
    Keep up the good work, and Thank you for keeping us safe!

  • Thanks for this. Since you asked ... Speaking only for my site and my opinion, I'd like to go much further. I'm the only authorized editor of my site, although that could change. As such, I want NO outside world accessible automation available. NONE! Unless someone visits the site with a traditional web browser AND requests a URL permalink that I've created to one of my pages or posts, I want them to hit a brick wall and get nothing but an error message. I entered a trouble ticket saying that I needed to operate in whitelist mode rather than blacklist mode, to only allow out what I approve rather than trying to block all that I don't like. I have plugins that disable json and xmlrpc but I'd rather that Wordfence have that option built in so I don't have to use those other things. All these fancy new automation features just open up too many attack vectors in my opinion. I have to spend hours each week kicking attackers off my blog from virtually every country. The last thing I want to do is give them access to any automation to help them. However, thanks for a great product. I find it very useful.

    Ron

  • Just to know!
    That option is not working. I have to go to Wordfence Options from every Wordpress installation that i have and have to hit Save again and then the option for preventing of discovery of usernames is working. Sorry for my english.

  • This is why I use your plugin. Thank you for being ahead of the game!

  • These people at the REST API team should be arrested for creating a public hazard. Seriously. They whip this stuff out like they're at a 1965 lovein festival and everyone is wandering around stoned out of their minds and thinking the world is like a warm bath, with no evil. Sick of this. I've got REST API disabled, the nightmare is if Wordfence starts using it, then I'd have to turn it on!

    It seems like it's time to run, not walk, from Wordpress. But finding the time and energy to do that is pretty much impossible for many of us trying to make a living. We're stuck with Wordpress because we bought into the hype so many years ago. But it's not easy, and seems to get more difficult all the time.

    • Hi, I'm the one who wrote the code in the REST API. :)

      To be clear: the usernames exposed via the REST API are already exposed elsewhere in WordPress on the public side. They're available in URLs, and various places in the theme. The REST API exposes them here since they're already public, according to existing parts of WordPress.

      We took very careful steps to ensure that nothing new is exposed via the REST API, and all of the data in it is already exposed in WordPress by default.

      That's not to say that the WordPress defaults are for everyone. There are plugins out there that change the public URLs and hide this data as much as possible, and I think it's important that these plugins exist for users to have the option. It makes sense for those plugins to update to handle this newer case as well.

      I'm all for the ability to choose, and I'm glad Wordfence added this option to allow everyone to hide this data if they choose. They've also done so in a technically-sound way that should minimise breakage.

      Happy to elaborate on any point.

      • Thanks Ryan. Sorry about the delay in approving this comment. It came in at 11pm last night and I just got into comments now to moderate.

        We appreciate the feedback.

        Mark.

      • Quoting @Ryan McCue December 13, 2016 at 11:00 pm

        "There are plugins out there that change the public URLs and hide this data as much as possible, and I think it's important that these plugins exist for users to have the option. It makes sense for those plugins to update to handle this newer case as well."

        Can someone please specify what those plugins are? I know WordFence specifically blocks the /users URL, but I have experienced an attack on the /pages and /posts public URLs and would like to be able to disable those as well, *without* having to disable the API entirely (similarly to how WordFence has handled the /users URL).

        I am hoping this attack was due to the "newness" factor and once the urchins realize that they aren't actually getting anything they don't already have, this will settle down. But for now I have to guard my CPU usage (which was sent into catastrophic levels during the attack) so that I don't get kicked off my hosting service (which is SiteGround, one of the WordPress recommended hosting service). I have removed the 4.7 test installations completely and my CPU usage and traffic levels have returned to normal.

        At this point, however, I have to agree that the WordPress REST API developers are being a little bit naive about what is "already public" vs. what is another possible attack vector.

        While there may not be any security issues within the API code, attackers used the public API URLs as an attack vector and nearly got me removed from my web hosting account.

        The short story is that I felt the API documentation was a little lacking and so I installed two test copies of WP 4.7 in previously unused subdirectories with relatively "random" names (one each on two servers I use), just to play with it and try to figure out what I could until the doucmentation is updated.

        Within hours the public API URLs were being flooded with calls from Bulgaria, in particular. This lead to *both* of my accounts going into a CPU tailspin that nearly got my accounts banned from my service provider, on two different servers.

        I am wondering if anyone else has noticed that their public API calls have been flooded at any point?

        eg:
        yourdomain.com/wp-json/wp/v2/pages
        yourdomain.com/wp-json/wp/v2/posts
        yourdomain.com/wp-json/wp/v2/users

        (there are more, but these are the ones that were flooded, during this particular attack)

        The API "pages" call (mydomain1.com/randomsubdirname/wp-json/wp/v2/pages) got 20,000 views in one hour, within about 5 hours of installing a completely brand new installation of WordPress, in a previously unused subdirectory, in a hosting account that barely gets 5,000 page views per month, normally.

        Not only do these public API URLs appear to be a target for possible DOS attacks, I think the WordPress core team are also being very insensitive about privacy vs. security and that some content publishers may not want their content to be distributed in this manner, regardless of whether it's "already public" or not.

        I am concerned about the attack vector risk and I also am disappointed that we didn't just start out with the ability to choose to close these public URLs, from within WordPress 4.7, without having to disable the API completely, for whatever reasons we may want to.

        I have looked but I have not found a plugin that hides these public API urls without disabling the API completely, except for WordFence that disables the /users URL, but none of the others.

        Any help here? Thanks!!

  • I had wp 4.7 and didn't even have the new wordpress and even when I disabled that option I still couldn't list usernames going to that url you mentioned gave some kind of routing error

    • Meant to say didn't have the new wordfence

  • thanks. as others said already: you rock!

    when i open that url on my site i get the following in text only:

    {"code":"rest_user_cannot_view","message":"Du bist leider nicht berechtigt, Benutzer aufzulisten.","data":{"status":401}}

    shouldn't that be somehow "prettier", say, as a message inside the normal theme of the site?

    • No.

    • No, because it's a JSON API it should respond in JSON valid syntax.
      Learn more here: https://en.wikipedia.org/wiki/JSON#Example

      If you want to see the normal response of the JSON API without protection:
      https://wordpress.org/news/wp-json/wp/v2/users

  • Thank you for this useful information. I'll go to update :-)

  • Thank you so much for Wordfence! Awesome protection and education. You and your team are my heros :)

  • I think you made the right decision by blocking this anonymous user list enumeration. However on a public wordpress website a simple robot could scavenge all posts and grab the author name and username from each post. So in a way it's not less secure then before. And both ways have the same kind of guessing of wich username is the admin. Probably the first post ever is done by him.

    I wonder about a site where most posts are not publicly visible, such as you need to register and get approved first before you can reads the posts. If in such scenario the JSON API lists all users than that is sort of a security breach. As you can get information that was otherwise not publicly available.

    Just my 2 cents.

  • Hello, but if I am logged in as admin in WP, example.com/wp-json/wp/v2/users should
    just be working JSON fine; but this is also disabled. Why? BR

  • Thanks for this. I've blocked all access to authors on my website, or at least I had till I upgraded Wordpress to latest version. I have a child theme and went through and took author out of all pages and posts. I blocked author enumeration within my nginx config global security settings file.

    To prevent DDOS type activity I have Nginx rate and connection limiting and fail2ban adding firewall rules on both the servers and cloud flare if limits are breached. I also allow nginx to cache api responses for 10 mins if not logged in. Nginx can comfortably handle the rates keeping requests away from Wordpress for those 10 mins and rate limiting kicks in if they get silly.

    I'll add new rules for the api tomorrow to block the /users/ route.

  • Great job! Thanks for nice info bro!