WordPress – Disabling XML-RPC and Rest API to improve security


To totally unlock this section you need to Log-in

In WordPress we have always had inbuilt features that let us remotely interact with our site. It is useful to have this kind of opportunity, as sometimes you will need to access your website and your computer won’t be anywhere nearby. For a long time, the solution was a file named xmlrpc.php.

xmlrpc.php

Let's begin by viewing what are the components on which xmlrpc.php is based:

  • RPC is Remote Procedure Call – This helps you to call a procedure remotely from a workstation or a device.
  • XML (Extensible Markup Language) – This particular language is framed to store and transport data, pretty much like HTTP.
  • HTTP (Hyper Text Transfer Protocol) – It is an application protocol that defines how the messages will be formatted and further transmitted over the World Wide Web. The protocol also determines the actions of both the web servers and browsers in response to the commands. In this case, with the help of HTTP, the data can be easily transferred from a remote device to a website.
  • PHP (Hypertext Pre-processor) – It is a scripting and programming language. This particular language mainly serves dynamic websites. It is used to strike a conversation between: the user, the website and the databases.

Now let's see a xmlrpc.php example/scenario: let’s say you wanted to post to your site from your mobile device since your computer was nowhere nearby. You could use the remote access feature enabled by xmlrpc.php to do just that.

Back in the early days of the internet, when the connections were incredibly slow, the process of writing and publishing to the web was much more difficult and time-consuming. Instead of writing within the browser itself, most people would write offline, then copied and pasted their content onto the web. Still, this process was far from ideal.

The solution (at the time), was to create an offline blogging client, where you could compose your content, then connect to your blog to publish it. This connection was done through XML-RPC. With the basic framework of XML-RPC in place, early apps used this same connection to allow people to log in to their WordPress sites from other devices.

xmlrpc.php is a feature that allows remote connection to a WordPress environment/site. This API offers developers of desktop apps and mobile apps an ability to communicate to a WordPress website and offers developers to write applications that empower you to do numerous things whenever you are logged in to WordPress through web interface including: whenever you upload a new file such as an image for a post, or edit comments, or edit a post, or delete a post, or publish a post, or get a list of comments.

So, technically speaking, with xmlrpc.php file a remote procedure call gets facilitated. This is done using XML to encode the message and send it across HTTP. Using this, information can be exchanged between devices or computers.

Finally, to decide if you need XMLRPC, you have to first understand what functions does the XMLRPC serves on your WordPress website. The file serves three primary functions:

  • WordPress App – If you use the WordPress app on your mobile device to post to your site, you need XML-RPC. The app uses this function to communicate to your WordPress website by making a remote connection.
  • Trackbacks and pingbacks – When you publish content, if you have provided a link to another blog or a website, this feature will alert the other website that you’ve linked to them. Trackbacks are created manually while pingbacks are automated. If you use these options, you need access to the XML-RPC.php file to be enabled.
  • JetPack plugin – JetPack is a popular plugin that is used by over 5 million WordPress sites. It offers services related to security, performance and site management. It uses XML-RPC to communicate with WordPress.com. If you’re a subscriber of JetPack, you need XML-RPC enabled.

The following two kinds of attacks on XML-RPC have received press coverage in the past (with the newer versions of WordPress software the following should not be doable, unless the WordPress site is still not updated):

  • DDoS via XML-RPC pingbacks: this was actually not a very effective form of DDoS and anti-spam plugins like Akismet have gotten good at spotting this kind of abuse.
  • Brute force attacks via XML-RPC. These are completely ineffective if you’re using an approach/plugin to simply block the attacker after they reach the login attempt limit.

Disabling xmlripc.php

If you disable the XML-RPC service on WordPress, you lose the ability for any application to use this API to talk to WordPress. Let's say that you have an app on your smartphone that lets you moderate comments.

After a while, you decide, to harden your environment, to disable XML-RPC: as a consequence, the app will suddenly stop working because it can no longer communicate with your website using the API you just disabled. But this scenario is not critical at all, if you are not going to monitor/interact with your WordPress environment from a remote location with no web browser access to the site.

There are several ways to disable xmlrpc.php (without just deleting it from the hosting space or directly from the web server, because it will be there again the next time you will update your WordPress environment, in any case); the first one we will see is by modifying the .htaccess file, if using an Apache web server.

Adding the following code snippet to your .htaccess file will prevent the xmlrpc.php to be available (accessible) from anyone:

# Block WordPress xmlrpc.php requests
<Files xmlrpc.php>
order deny,allow
deny from all
allow from 100.100.100.100
</Files>

Using Apache 2.4's newer access control syntax, it will be:

<files xmlrpc.php>
    Require all denied
</files>

For sites hosted on Nginx, you can add the following code to the nginx.conf file:

location ~* ^/xmlrpc.php$ {
return 403;
}

Or, you can simply ask your web host to disable XML-RPC for you.

Disable WordPress XML-RPC Using a Filter

Alternatively, you can add a filter into any plugin (or in a custom simple plugin):

add_filter('xmlrpc_enabled', '__return_false');

Disable WordPress XML-RPC Using a Plugin

Another quick and simple way to disable XML-RPC in WordPress is by using the Disable XML-RPC plugin by Philip Erb, that is able to turn off the XML-RPC service running on WordPress 3.5 and above. Here is the steps to activate the plugin:

  • Upload the disable-xml-rpc directory to the /wp-content/plugins/ directory in the WordPress installation.
  • Activate the plugin through the Plugins menu in WordPress.
  • XML-RPC is now disabled.
  • To re-enable XML-RPC, just deactivate the plugin through the Plugins menu.

Obviously, you can install this plugin also by using the embedded plugin search engine inside the Admin area in the WordPress specific website.

WordPress REST API

The WordPress Rest API is a developer-oriented feature in WordPress (with a similar goal as XML-RPC). The WordPress REST API provides API endpoints for WordPress data types that allow developers to interact with sites remotely by sending and receiving JSON objects.

NOTE: As of WordPress 4.7, the filters provided for disabling the REST API were removed.

This is done by mapping different endpoints through a URI, such as:

https://example.com/wp-json/

While the WordPress REST API is great, one problem is that by default, it leaves the usernames of anyone who has published on your WordPress site wide open via the following URL:

https://example.com/wp-json/wp/v2/users

Allowing this kind of information to be readily visible may not be something you want, as crackers will start to guess passwords against all the usernames on your WordPress website.

This would enable them to begin brute force attack. You probably don’t want even the secure usernames to be readily available.

You can disable the WP-JSON REST API using some code and adding it into the functions.php file of the WordPress site. However, we are going to go over a much easier way to disable the JSON REST API using a great plugin. We need also to consider that, in general, disabling WP-JSON REST API should be safe, especially for those site which is not used by external apps; by "safe" here we mean that it does not cause unexpected side-effects, e.g. does not break any other WP core functionality.

Method 1 - Disable REST API Plugin

The Disable REST API plugin is the most comprehensive and complete plugin available for controlling access points to the WordPress REST API. The plugin is lightweight and very easy to use.

It acts as a plug-and-play type of plugin, as the only settings available will be checkboxes next to your website items. Upon activation, the plugin automatically ensures that the entire REST API is protected from non-authenticated users.

Wordpress - Disabling XML-RPC and Rest API to improve security

As showed in the above image, on the checkbox layout that is on the Settings page you can pick and choose which applications, tools, and plugins you want using the REST API, so, basically, checking the endpoint in the Settings page of the plugin will allow the relative REST API. The number of checkboxes available and the amount will be directly connected to everything you are running on your WordPress website. So the more you have, the longer the list will be.

The plugin download, as a mirror and as a .zip archive, will be available at the end of this article, under the Download section.

Method 2 - Disable REST API

Another quick, and effective, solution, not to disable the REST API of WordPress, to force the access to the REST API only for logged on users, is the following; the below code can easily be added to the functions.php or to a custom plugin:

//** Start Disable REST API **/
add_filter( 'rest_authentication_errors', function( $result ) {
    if ( ! empty( $result ) ) {
        return $result;
    }
    if ( ! is_user_logged_in() ) {
        return new WP_Error( 'rest_not_logged_in', 'Not allowing the REST API.', array( 'status' => 401 ) );
    }
    return $result;
});
//** End Disable REST API **/

An alternative way to achieve the same goal of the above code (accessing the REST API only after being logged in) is the following:

add_filter( 'rest_authentication_errors', 'disable_rest_api_logged_in' );

function disable_rest_api_logged_in( $access_deny ) {
    if ( ! empty( $access_deny ) ) {
        return $access_deny;
    }
    if ( ! is_user_logged_in() ) {
        return new WP_Error( 'rest_api_disabled', 'You are not logged in.', 
            array( 'status' => rest_authorization_required_code() ) );
    }
    return $access_deny;
}

Instead, to completely, and really, disable all the REST API endpoints we could use the following code:

add_filter( 'rest_authentication_errors', 'disable_rest_api' );

function disable_rest_api( $access_deny ) {
     return new WP_Error( 'rest_api_disabled', __('REST API has been disabled.'),
        array( 'status' =>  rest_authorization_required_code()));
}

Finally, we could consider another approach about REST API, disabling the public access to the default endpoints, but enabling all the endpoints once logged in:

// Disable some endpoints for unauthenticated users
add_filter( 'rest_endpoints', 'disable_default_endpoints' );
function disable_default_endpoints( $endpoints ) {
    $endpoints_to_remove = array(
        '/oembed/1.0',
        '/wp/v2',
        '/wp/v2/media',
        '/wp/v2/types',
        '/wp/v2/statuses',
        '/wp/v2/taxonomies',
        '/wp/v2/tags',
        '/wp/v2/users',
        '/wp/v2/comments',
        '/wp/v2/settings',
        '/wp/v2/themes',
        '/wp/v2/blocks',
        '/wp/v2/oembed',
        '/wp/v2/posts',
        '/wp/v2/pages',
        '/wp/v2/block-renderer',
        '/wp/v2/search',
        '/wp/v2/categories'
    );

    if ( ! is_user_logged_in() ) {
        foreach ( $endpoints_to_remove as $rem_endpoint ) {
            // $base_endpoint = "/wp/v2/{$rem_endpoint}";
            foreach ( $endpoints as $maybe_endpoint => $object ) {
                if ( stripos( $maybe_endpoint, $rem_endpoint ) !== false ) {
                    unset( $endpoints[ $maybe_endpoint ] );
                }
            }
        }
    }
    return $endpoints;
}

How to find and view the data - Quick REST API overview

Accessing all of your site data via the REST API is as simple as composing a URL, and that's why below are presented some info about REST API for WordPress and to get an idea on why it should be restricted (the examples below are based only on GET requests, but the same approach, with obvious modifications, can be used for POST and PUT requests, that can actually modify the WordPress content).

For any WordPress site running at least version 4.7 (and above), add the following string to the end of your site’s mail url: /wp-json/wp/v2 (e.g., https://example.com/wp-json/wp/v2). Put that URL in your browser: the result probably will look like a big mess of data, unless you’ve installed a browser extension that cleans up JSON (JSON Viewer).

That big mess of data is the content and meta information of your particular WordPress site in JSON format.

By loading that content, you’ve just defined a route and asked your browser to GET it for you.

A route is a URL that’s mapped to a specific method. WordPress core reads that route, with every slash ‘/’ representing a particular path, or parameter, that should be followed.

The path concludes at an endpoint, where functions deep inside of WordPress core can make decisions about what data to provide and what to do with any data that was provided.

Using curl, a free command line tool used on Linux to interact with web resources (on Windows we can use the best API client available, Postman), we can construct an HTTP call to the REST API. The base of every WordPress REST API call is as follows:

http://example.com/wp-json/

Testing the connection by executing the curl command, with the above URL, on a WordPress website, will output, successfully, something similar:

curl -X OPTIONS -i http://yourdomain.com/wp-json/

HTTP/1.1 200 OK
Date: Wed, 23 Oct 2019 19:51:41 GMT
Server: Apache/2.4.29
X-Robots-Tag: noindex
Link: ; rel="https://api.w.org/"
X-Content-Type-Options: nosniff
Access-Control-Expose-Headers: X-WP-Total, X-WP-TotalPages
Access-Control-Allow-Headers: Authorization, Content-Type
Allow: GET
Transfer-Encoding: chunked
Content-Type: application/json; charset=UTF-8

Next, you can rinse and repeat this command using several endpoints. This time, we will simply use the GET version of curl to grab a JSON list of your WordPress posts. To do that, you can use the following command:

curl -X GET -i http://example.com/wp-json/wp/v2/posts

We can also retrieve all existing WordPress pages by using another endpoint:

curl -X GET -i http://example.com/wp-json/wp/v2/pages

Another example of a REST request could be select a specific post, before by finding the ID of a post you’d like to select (this can be find mainly in the WordPress Admin area). Then we will need to add the ID to the end of a similar below query in order to select an individual post:

curl -X GET -i http://example.com/wp-json/wp/v2/posts/


Summary
Article Name
Wordpress - Disabling XML-RPC and Rest API to improve security
Description
In WordPress we have always had inbuilt features that let us remotely interact with our site. We have two different approaches available: XML-RPC, a legacy method, or the newer Wordpress REST API that simplifies the remote interactivity and development of external apps. We can disable both of them if we do not need any remote access to the site and/or we do not use any app for the Wordpress resource.
Author
Publisher Name
Heelpbook.net

1 thought on “WordPress – Disabling XML-RPC and Rest API to improve security”

Comments are closed.