Security

Joomla's Web Services API: what it exposes and how to close what you don't use

Joomla's Web Services API: what it exposes and how to close what you don't use

Joomla 4+ has a REST API in /api that can read articles, users and configuration. How it is protected, how to test it with curl, and how to close it.

Every Joomla site since 4.0 has a second front door. Next to the site and the administrator there is a third application in the api/ folder: a REST interface that can read and write articles, users, menus, modules, extensions and the global configuration. It is switched on after a fresh install, and most site owners never look at it. That is fine as long as it is locked properly, but it is worth knowing what is behind that door and closing the parts you do not use.

What the API is made of

The API lives at https://example.com/api/index.php/v1/. The routes themselves come from plugins in the webservices group: Web Services - Content, Users, Menus, Modules, Plugins, Templates, Config, Media, Languages, Installer and a dozen more. Each plugin adds one set of endpoints. Out of the box, nearly all of them are enabled.

Who may call those endpoints is decided by a second group of plugins, api-authentication:

  • API Authentication - Web Services Joomla Token is enabled by default. It accepts a token in the X-Joomla-Token header (or Authorization: Bearer).
  • API Authentication - Basic Auth is disabled by default. It accepts a username and password with every request. Leave it off.

The tokens come from a third plugin, User - Joomla API Token. It adds a "Joomla API Token" tab to the user profile. Its "Allowed User Groups" option defaults to Super Users, so on a standard site only Super Users can get a token at all. Even then, the token only works while the account is enabled and the token itself is switched on in the profile.

A request without a valid token gets a 401 with a JSON error. Normal ACL still applies after login: an API user can do exactly what that account could do in the administrator.

Why this matters: the 4.2.7 leak

In February 2023 Joomla released 4.2.8 to fix CVE-2023-23752. On versions 4.0.0 to 4.2.7, an access check in the web services layer could be skipped by adding ?public=true to the URL. The worst case was this request:

/api/index.php/v1/config/application?public=true

It returned the global configuration without any login, including the database user and password. Automated scanners still try that URL on every Joomla site they find. If your server logs show hits on /api/index.php/v1/config, that is why. A current Joomla 4, 5 or 6 is not vulnerable, but the episode shows what the API can hand out when one check fails.

Check what your site answers

From your own machine, without a token:

curl -i https://example.com/api/index.php/v1/content/articles
curl -i "https://example.com/api/index.php/v1/config/application?public=true"

Both should come back with 401 and a short JSON error. If you get article data or configuration values, stop reading and update the site first. A 404 means the Web Services plugin for that route is disabled, or the API is blocked at the server, which is also fine.

Turn off what you do not use

Most brochure sites, blogs and shops do not use the API at all. No mobile app, no headless front end, no sync with an external system. In that case:

  1. Go to System > Manage > Plugins and filter on type webservices. Select all and disable them.
  2. Filter on type api-authentication and disable both plugins. Without an authentication plugin no request can log in.
  3. Open User - Joomla API Token and either disable it or set "Allowed User Groups" to a group with no members.

If the API is used, keep only the plugins for the endpoints you need. A site that pushes articles from an external editor needs Web Services - Content, and maybe Media and Tags. It does not need Users, Plugins, Installer or Config. Every disabled plugin is a route that can no longer be abused, whatever bug turns up next.

Block the folder at the server

When nothing on the site uses the API, you can also refuse the requests before PHP starts. With Apache, add this to .htaccess just after RewriteEngine On, above the rules Joomla ships for api/:

RewriteRule ^api/ - [F,L]

On nginx:

location ^~ /api/ {
    return 403;
}

Test with the curl command above: you should now get a 403. Write the change down somewhere. The next developer who connects an app to the site will otherwise spend an afternoon wondering why every call is refused.

If you do use it: a separate user per integration

  • Do not use your own Super User token in an integration. Create a dedicated account per integration, give it a group with only the permissions it needs, and add that group to "Allowed User Groups" in the User - Joomla API Token plugin.
  • Store the token where the integration keeps its other secrets, not in a script in the web root.
  • The token is derived from the site secret ($secret in configuration.php). Changing that value makes every existing token invalid at once, which is a quick way to cut off all integrations after a leak. Joomla also uses the secret elsewhere, so test the site afterwards.
  • To stop one integration, disable its token in the user profile or block the account. Calls made with that token fail immediately.
  • Changes made through the API show up in the user actions log under the API account's name, which is one more reason not to share an account between integrations.

Short checklist

  • Joomla is on a current release, so at least past 4.2.8.
  • Unauthenticated curl to /api/index.php/v1/content/articles gives 401, 403 or 404.
  • Only the Web Services plugins you actually use are enabled.
  • Basic Auth is disabled.
  • Each integration has its own user with limited rights.

It takes ten minutes, and it is the same habit as with the security headers plugin: Joomla already has the switches, they just are not set for your site yet.

Stuck on something else?

Doctor Joomla is a project of Cloudfaction, a Dutch agency building and maintaining Joomla sites since 1999. The articles are made with the help of AI, so tell us if something does not match your screen. Mail info@cloudfaction.nl if you want someone to look at yours.

Rather have someone look at it

Doctor Joomla is a Cloudfaction project.

A Dutch agency that has been building and running Joomla sites since 1999. If your site needs more than an article can fix, get in touch.