Information Disclosure Vulnerability in WordPress REST API

WordPress is insanely popular. Around 43% of websites on the internet use WordPress. I don’t know how it’s come to this, as WordPress is not that great. But, aside from being a relatively easy writing platform for hobbyist bloggers like me, it’s also very prevalent among digital marketing companies, who build their own websites and those of their customers on WordPress.

As a result, bugs and security flaws in WordPress are not to be taken lightly, no matter how small.

Listing Users

I came across the following in the book Hacking APIs: Breaking Web Application Programming Interfaces by Corey J. Ball:

“Sensitive data can include any information that attackers can leverage to their advantage. For example, a site that is using the WordPress API may unknowingly be sharing user information with anyone who navigates to the API path /wp-json/wp/v2/users, which returns all the WordPress usernames, or “slugs”.”

— Hacking APIs: Breaking Web Application Programming Interfaces by Corey J. Ball (2022), page 54

Indeed, I was able to simply append /wp-json/wp/v2/users to the URL of several WordPress sites and see a list of users. For instance, this is from a fresh WordPress install:

A list of users shown in a fresh install of WordPress.

The following, on the other hand, is a list I got from a company website:

A list of users from a company website, obfuscated to protect their identity. You can also see they use the Yoast SEO plugin.

The following is from another company website, which has been protected with a plugin, but reveals the name of the plugin used:

The list of users from this other website is restricted by the iThemes Security plugin.

We’ll discuss in the next section why revealing the names of plugins you use, like Yoast SEO or iThemes Security, is probably not a good idea.

Meanwhile, as we have seen, it is very easy to get a list of users, including their full name and username, for a WordPress website. Unfortunately, the WordPress REST API, of which wp-json is the top-level endpoint, is enabled by default.

To be fair, it’s also possible to find out the users of a WordPress site by just checking its blog posts and taking note of the author. The link to an author exposes the username, instead of using something more generic like an id.

Either way, once an attacker knows the usernames pertaining to a website, all that’s left is to figure out a password. They could brute force a password for one of the users or else attempt a set of weaker passwords for several users and see if any fit (a technique known as password spraying). It also doesn’t help that it’s universally known that WordPress sites have their login page at /wp-admin. Having strong passwords is more important than ever.

Listing Plugins

There is also a wp-json/wp/v2/plugins endpoint, which presumably could give us a list of plugins, but it does seem protected by default:

The plugins endpoint doesn’t tell us anything.

However, we can still get a lot of information about plugins by just expanding routes at the top-level wp-json endpoint. For instance, the screenshot below shows that this website uses Elementor, Gravity Forms, and Google Site Kit among other things. It is also possible to find out plugin names from other places, as shown in the previous section.

Expanding routes exposes the names of many plugins used by a WordPress website.

Knowing the plugins used in a website, an attacker could look up known vulnerabilities, e.g. on WPScan, and attempt to exploit them.

Disabling the REST API

Just because an attacker knows your users’ usernames or plugins, it doesn’t mean they will manage to compromise your website, or that they couldn’t do it without that knowledge anyway. But it’s conventional wisdom in IT security that we can sleep more comfortably at night if we don’t make it easy for bad actors to destroy what we worked so hard to build.

An easy way to stop sharing all this information is to disable the REST API altogether. As with everything else in WordPress, this can be done with a plugin.

The Disable REST API plugin.

Simply find, install and activate the Disable REST API plugin. This will protect the REST API:

With the REST API disabled, we can’t see the list of users any more.

Some notes:

  • This protects the entire API, not just the users endpoint shown above.
  • In the plugin’s settings, you can configure any endpoints you want to remain accessible.
  • “DRA” does expose the name of the plugin. It’s not perfect but reduces risk considerably.
  • You should test this from an incognito browser window. If you access the API from a browser where you’re logged into WordPress, you’ll likely see the regular API response simply because you’re authorised.
  • There’s another way to disable the REST API using the WPCode plugin instead.

Conclusion

Given how much information the REST API provides to basically everyone, it’s a little shocking that it’s enabled by default. By disabling it, we can make attackers’ lives a little harder and reduce the security risk of our WordPress websites.

Leave a Reply

Your email address will not be published. Required fields are marked *