Limit access to WordPress API without authentication
Multiple instances were found to expose user's information, this is more problematic on instances where owners have set up the OIDC plugin, making at least upns
available. Instances without OIDC setup are not as "badly" affected.
Some instance examples, with OIDC plugin:
- https://cds-blog.web.cern.ch/wp-json/wp/v2/users
- https://club-orientation-wp.web.cern.ch/wp-json/wp/v2/users
- https://lhcb-outreach.web.cern.ch/wp-json/wp/v2/users
- https://wit-hub.web.cern.ch/wp-json/wp/v2/users
Without OIDC plugin enabled:
- https://higgs-2022.web.cern.ch/wp-json/wp/v2/users
- https://malt-internal.web.cern.ch/wp-json/wp/v2/users
- https://msenger.web.cern.ch/wp-json/wp/v2/users
- https://qtml-2023.web.cern.ch/wp-json/wp/v2/users
From my understanding, ALL WordPress instances will expose these values by default, some notorious instances upstream have it too, example: https://blog.mozilla.org/wp-json/wp/v2/users
This does not occur by default, WordPress configurations must be changed in order to have the API working and exposed. An example is editing the Permalink structure
, an action with no expectation of exposing the API, yet it does.
To solve the exposed API, a common approach is to protect it with authentication (as seen here for example: https://uk.usembassy.gov/wp-json/wp/v2/users), which can be achieved with a plugin. There are other possible approaches which include adding a code snippets to WordPress or editing Apache rules to deny accessing the API endpoints.
Suggestion:
Going with a plugin. Even though a plugin can latter be uninstalled by an user, it can be added to the WordPress image and it is not disruptive in enabling it if necessary. It's also "modular" so it can later be removed or replaced with simplicity (unlike a code snippet). An Apache rule would cover the protection as well but would not allow to have users using the API later on if required as it would be embedded into the image and immutable. If deemed that the API should not be used in any case, then the Apache rule can be a more relevant approach.
If the plugin approach is to be considered, these are some options:
- https://wordpress.org/plugins/stop-user-enumeration/ (suggested by Stefan from the Security Team)
- https://wordpress.org/plugins/disable-json-api/ (Bigger community adoption, makes the API behind authentication)
The second plugin has been tested, and can be seen here:
- https://fborgesa-wp.web.cern.ch/wp-json/wp/v2/users If logged in, it will work, otherwise won't, this reduces any negative impact of possibly disabling the API altogether, but also protects all API requests and not just the user enumeration.