Support » Requests and Feedback » Why is the REST API enabled by default?

  • Hello, I have a website, but I am sure it is not only my website, hundreds, thousands of websites have their REST API exposed (though read-only). After enabling pretty permalinks all the REST API is exposed and enabled on website.com/wp-json.
    Almost any website has the API exposed and visiting /wp-json/wp/v2/users helps me find easily which users are registered. This should be considered a security issue, not because of the technical difficulties, but because a lot (if not the whole) of the information from the website is exposed.
    Maybe there is a wordpress ticket about this, but I was not able to find it.

Viewing 14 replies - 1 through 14 (of 14 total)
  • Moderator Steve Stern

    (@sterndata)

    Support Team Volunteer

    WordPress uses the REST API itself, so it needs to be enabled for things like the new editor. Plugins can modify the user listing issue — install WordFence. for example:

    See https://i.imgur.com/zJRIBy4.png

    WordPress uses the REST API itself, so it needs to be enabled for things like the new editor

    But it should be then available by default for wordpress only and users with the correct rights, not for everyone?!

    Moderator Andrew Nevins

    (@anevins)

    WCLDN 2018 Contributor | Volunteer support

    If you’re looking for an answer as to why that is, it’s that usernames aren’t considered as part of security.

    This is not only about security, but privacy as well. /wp-json/wp/v2/media shows files from the media gallery, but these files are not always meant for the public use (people might decide that certain files are only visited after a user is logged and goes to the media dashboard, just one of the many use cases). Is there really no general settings about the rest endpoints? I know that Gutenberg needs the endpoints.. to work at all, but it makes sense, that whoever edit posts, should be able to access the api too (though maybe not all endpoints). This should not be only considered as a security issue, but as a privacy one. The worst think – it is not flexible for the normal user. I know it takes 5 lines of php code to disable the api for the public, but why not a goddamn setting in the settings panel for that?

    Moderator Jan Dembowski

    (@jdembowski)

    Forum Moderator and Brute Squad

    @katsar0v Don’t create duplicate topics. I’ve closed your other topic.

    tl;dr You can disable that via a plugin. I use this one.

    https://wordpress.org/plugins/disable-wp-rest-api/

    For added security add a 2FA plugin.

    https://wordpress.org/plugins/search/2FA/

    I personally use this one.

    https://wordpress.org/plugins/two-factor/

    Longer reply:

    There is nothing exposed by /wp-json/wp/v2/users that is not already exposed via https://some-site-url/author/userid/ and user name enumeration has never been about security. Nor will it ever be, the public portion of the login transaction is assumed to be well, public.

    For example: My user names are these.

    jdembowski Which you can get here https://profiles.wordpress.org/jdembowski/

    And here https://wordpress.org/support/users/jdembowski/

    And here https://make.wordpress.org/support/author/jdembowski/

    And even on my own site here https://blog.dembowski.net/author/jan/ as jan which doesn’t work because I broke my site in a little way. The links are on each of my 900+ blog posts there though.

    And on Twitter too https://twitter.com/jan_dembowski/ as jan_dembowski

    I can also log into any of those systems using my email address which I will not publish ’cause spam. It’s not really a secret though and no, do not post anyone’s email here to make a point.

    All of my systems use passwords like this.

    2XbM*aTA9qtgV!HUy_LC@c
    mDjAt323viF@pW3dZbtN!a
    PhYPvPPEjkb3qu*x@ZykEa

    I use a tool called 1Password to generate those though there are many others. When I’m feeling particularly security conscious I enable 2FA for the logins.

    Anything that you cannot explicitly control such as your user ID cannot be considered part of a security solution. That’s why you have passwords and in many places 2FA or even MFA (which is cool). Your user ID like your email address is just an identifier. It’s never meant to be secret and in the case of your email address, you hand it out all the time.

    You didn’t write the below quote but I’m trying to be complete.

    But you use a plugin to disable REST API for non-logged in users.

    Yes, but not for security. I’m trying and failing to filter Gravatars in REST API responses. I installed that plugin to see how it works.

    (Gravatars potentially expose email addresses and I substitute them for an inline base64 encoded image. I don’t think it’s a threat either but I had an afternoon free.)

    If you make the user ID secret, you now have two secrets. And if your secret user ID is out there what recourse do you have? Get a new user ID? You can change your password as often as you like. That was it’s designed purpose and that’s where security is addressed.

    Use strong passwords. Add 2FA if you feel it is necessary. But don’t place security in your user ID. That’s not it’s intended purpose anywhere.

    • This reply was modified 4 weeks, 1 day ago by  Jan Dembowski. Reason: Silly typos

    @jdembowski

    Thank you for the detailed reply. Is there a specific reason why this rest API is not adjustable by the WordPress Core (here I mean the default installation and settings page)?

    It has already happened several times that the core “consumed” some plugins in itself, so the functionality already exists when you install WordPress. I understand your point of view and you are correct about the urls (though mostly this is up to the theme whether authors and comments are shown and etc.)

    here is nothing exposed by /wp-json/wp/v2/users that is not already exposed via https://some-site-url/author/userid/ and user name enumeration has never been about security

    I would kind of disagree here, I am not trying to be technical, but rather look from a blogger / simple user perspective. Technically what /author/:id delivers id fully dependant from the theme. There are several fields of information (as well meta information) and the theme decides what to show – the use case is that you look for a theme, see the demo and see that there is an author page and what (as well how) is shown there. In the meantime whether you want it or not, the wordpress rest api just shows the information. Ok, you install the plugin, but wouldn’t it be better if those settings weren’t default (defensive strategy?)?

    The usernames shouldn’t be considered a security issue – you are correct again. But imagine you register on a wordpress website which has no /author/:id url. You cannot write articles, you registered because of the “premium” service (just a use case, one of the many that probably exist). Now this website does show article author information, however because you registered your account is exposed to /wp-json/wp/v2/users. I am repeating myself probably again here, but I just wanted to say this should be viewed as a privacy issue as well, not only security.

    (Gravatars potentially expose email addresses and I substitute them for an inline base64 encoded image. I don’t think it’s a threat either but I had an afternoon free.)
    The emails are exposed as well and this is again more a privacy then a security issue. A wordpress website cannot guarantee that the emails stay private if /wp-json/wp/v2/users basically exposes the md5 of your email. The MD5 hashing algorithm was once considered secure cryptographic hash, but those days are long gone. But this is too technical and I’d not bother for now (but a potential issue as well)

    The real-world use case with the obama foundation – the theme does not show any author information, /author/:name is not accessible, but the rest api lets you basically know who is the editorial team behind this.

    The funny thing though (I am not sure, but it is most probably true) is that the rest api respects the feed limitation from the settings page (which is by default 10). Also may not be a big issue, but the /wp-json endpoint reveals all endpoints also registered from other plugins and this exposes basically which plugin is installed on the website.

    Is there a way to escalate this into a “feature request” or discuss this topic with core developers? 5.3 or 5.4 version could easily include a minimal setting, that makes even a non-technical blogger aware, that information is exposed there. A switch could be also easily made, whether this to be private or not. It really should be not the case to install plugins for basic stuff, which should be done by the cms (my own opinion)

    PS: I created a trac ticket – https://core.trac.wordpress.org/ticket/48043#ticket

    Would be happy if someone else also shares his oppinion

    Moderator Jan Dembowski

    (@jdembowski)

    Forum Moderator and Brute Squad

    Thank you for the detailed reply. Is there a specific reason why this rest API is not adjustable by the WordPress Core (here I mean the default installation and settings page)?

    It’s not a option in any setting page because it does not serve any purpose to do so. It is not a risk. That’s why the plugin, filters and actions exists, to provide an option for the edge case where the user finds that desirable.

    As you are probably aware, it’s not a lot of code to disable that. Here’s from the plugin I suggested.

    https://plugins.trac.wordpress.org/browser/disable-wp-rest-api/trunk/disable-wp-rest-api.php

    Not a lot of code. 😉 Just some actions and filters.

    The real-world use case with the obama foundation – the theme does not show any author information, /author/:name is not accessible, but the rest api lets you basically know who is the editorial team behind this.

    How does that refute anything I’ve written? In any sense or form? Honest question.

    There is no privacy issue here either, just some behavior that you may find undesirable. Which leads to the suggestion to write some code or use a plugin. I myself prefer a plugin but the actions and filters are not difficult to work with.

    Is there a way to escalate this into a “feature request” or discuss this topic with core developers?

    Yes. Raise a trac ticket as you’ve done. Just don’t be surprised if it is not acted upon. It may be but the idea to reverse a designed feature that was implemented with intention isn’t often reversed.

    How does that refute anything I’ve written? In any sense or form? Honest question.

    It was just an example how the rest api might expose data the owner might not want to have public. The obama foundation itself is a showcase wordpress shows proudly, so that’s why I took it, but surely there are thousands of websites having the same issue.

    There is no privacy issue here either, just some behavior that you may find undesirable. Which leads to the suggestion to write some code or use a plugin. I myself prefer a plugin but the actions and filters are not difficult to work with.

    I don’t think this is just me, but if you think so, okay. There are exploiters and scripts automatically looking for wordpress vulnerability and /wp-json is like a golden mine now for them, because they can now easily find out which plugins are installed that use the rest api.

    I raised a trac ticket with feature request, as already said, am happy to read also some other opinions 🙂

    Timothy Jacobs

    (@timothyblynjacobs)

    You cannot write articles, you registered because of the “premium” service (just a use case, one of the many that probably exist). Now this website does show article author information, however because you registered your account is exposed to /wp-json/wp/v2/users.

    The REST API only returns users who have authored posts that show up in the REST API. Simply registering for an account shouldn’t show your user account in the /users endpoint.

    Also may not be a big issue, but the /wp-json endpoint reveals all endpoints also registered from other plugins and this exposes basically which plugin is installed on the website.

    Plugins can omit their REST Routes from the index by using show_in_index => false when registering their REST routes. However, the routes themselves will still be accessible. Additionally, plugins can already be determined by looking at the output of the page. References to CSS/JS/image files all include the plugin directory in the name.

    Without information / notification, somehow my comment was not approved or deleted. Whatever.

    Simply registering for an account shouldn’t show your user account in the /users endpoint.

    Good to know, thanks!

    About show_in_index, I guess it is true by default?

    @timothyblynjacobs what about the media files, are only the ones embedded in posts shown?

    For cpt the 'show_in_rest' => false, bydefault.

    https://en.wikipedia.org/wiki/Security_through_obscurity

    I guess wordpress does not follow “Security through obscurity”. Is wordpress aiming to be a headless framework with this rest api or what? I don’t fully understand the purpose of having fully open rest api exposing so much information, I hope someone enlightens me here.

    Moderator Steve Stern

    (@sterndata)

    Support Team Volunteer

    Security through Obscurity is an empty hope*, not a plan. Part of the REST API is, in fact, to allow WP to operate in a headless environment (e.g., backend to an app).

    * An Empty Hope is *not* the title of a Star Wars movie.

    @sterndata if headless is the reason, I saw absolute 0 talks in wordcamps across europe about it. Haven’t seen the docs mention headless (though i haven’t read them all).

Viewing 14 replies - 1 through 14 (of 14 total)
  • You must be logged in to reply to this topic.