The WordPress XML-RPC API has been under attack for many years. Back in August 2014, WordPress released version 3.9.2, fixing a possible denial of service issue in PHP’s XML processing. There are brute-force amplification attacks, reported by Sucuri, and so on. So, how do you protect WordPress from these xmlrpc.php attacks, optionally still being able to use (some of) its functionality like Jetpack? This post gives you some insights.
The problem: during a brute-force attack, HTTP requests keep coming in, knocking down webservers due to the sheer number of HTTP POST requests for /xmlrpc.php, and the increasing number of running PHP processes. This often consumes all available CPU and memory: a typical xmlrpc.php attack characteristic.
You want to protect your website and somehow block requests to xmlrpc.php. But you also want to use (some of) its functionality, like WordPress Jetpack. How?
One option is to add WordPress.com IP addresses to an allow list for xmlrpc.php
access through web.config
in Windows Server IIS or .htaccess
in Linux Apache, and block everything else.
WordPress xmlrpc.php allow list for WordPress.com, Automattic & Jetpack IP addresses
In a WordPress support ticket Jeremy Herve (@jeherve) provides some information about the required IP addresses in use for WordPress, Jetpack and other services.
If your hosting provider doesn't want to allow all connections to Jetpack, you can use these IPs:
All of the IPs listed at http://whois.arin.net/rest/org/AUTOM-93/nets
185.64.140.0/22
2a04:fa80::/29
So you need to allow these IP addresses. One big advantage of using an allow list, is that you automatically block all other IP's. Extra security for free :)
Add your own IP to the list if you need access too.
Create an IP allow list for xmlrpc.php in Windows Server IIS web.config
You can use the following web.config
snippet to allow IP addresses and ranges (netblocks) access to the xmlrpc.php file. All other IP addresses are blocked. The location
tag means the rules only apply to the path mentioned. In this case the file xmlrpc.php
.
<location path="xmlrpc.php">
<system.webServer>
<security>
<ipSecurity allowUnlisted="false">
<add ipAddress="64.34.206.0" subnetMask="255.255.255.0" allowed="true" />
<add ipAddress="192.0.64.0" subnetMask="255.255.192.0" allowed="true" />
<add ipAddress="185.64.140.0" subnetMask="255.255.252.0" allowed="true" />
<add ipAddress="76.74.255.0" subnetMask="255.255.255.128" allowed="true" />
<add ipAddress="76.74.248.128" subnetMask="255.255.255.128" allowed="true" />
<add ipAddress="198.181.116.0" subnetMask="255.255.252.0" allowed="true" />
<add ipAddress="2a04:fa80::" subnetMask="ffff:fff8::" allowed="true" />
<add ipAddress="2620:115:C000::" subnetMask="ffff:ffff:ff00::" allowed="true" />
</ipSecurity>
</security>
</system.webServer>
</location>
Find this information in Dutch at ITFAQ.nl: Blokkeer xmlrpc.php-aanvallen op Windows Server IIS.
Apache .htaccess mod_authz_host IP allow list equivalent
If you are on a Linux platform with Apache as its webserver, you can use the following .htaccess equivalent to create an allow list.
When using Apache 2.4.6+, you need to use a slightly different syntax for the Apache module mod_authz_host:
<Files xmlrpc.php>
# Help: https://httpd.apache.org/docs/2.4/mod/mod_authz_host.html
Require all denied
Require ip 185.64.140.0/22
Require ip 64.34.206.0/24
Require ip 192.0.64.0/18
Require ip 198.181.116.0/22
Require ip 76.74.248.128/25
Require ip 76.74.255.0/25
Require ip 2620:115:C000::/40
Require ip 2a04:fa80::/29
</Files>
Learn the WordPress .htaccess security best practices in Apache.
The example below is only for Apache 2.2, it's old and deprecated, but is mentioned here for completeness.
# Block access to xmlrpc.php for everyone
# except WordPress.com and Jetpack IP addresses.
#
# AllowList IP ranges in Apache 2.2 .htaccess using mod_authz_host:
# https://httpd.apache.org/docs/2.2/mod/mod_authz_host.html
<Files xmlrpc.php>
order deny,allow
allow from 185.64.140.0/22
allow from 64.34.206.0/24
allow from 192.0.64.0/18
allow from 198.181.116.0/22
allow from 76.74.248.128/25
allow from 76.74.255.0/25
allow from 2620:115:C000::/40
allow from 2a04:fa80::/29
deny from all
</Files>
What if WordPress/Jetpack IP addresses change?
Unfortunately you need to regularly check http://whois.arin.net/rest/org/AUTOM-93/nets to see if IP blocks have changed. Other options do exist. I hope this'll help you in keeping your site safe!
Block access to the xmlrpc.php file completely
Learn How to filter web traffic with blocklists
Another solution is to block requests to /xmlrpc.php completely, meaning you cannot use a plugin like Jetpack, or other functionality that relies on XML-RPC.
By Files directive in .htaccess
<Files xmlrpc.php>
Require all denied
</Files>
By IIS requestFiltering in web.config
In your IIS web.config file, add in the appropriate place:
<security>
<requestFiltering>
<denyUrlSequences>
<add sequence="xmlrpc.php" />
</denyUrlSequences>
</requestFiltering>
</security>
Using a Rewrite Rule
.htaccess
RewriteEngine on
RewriteRule \Qxmlrpc.php\E - [F,L,NC]
web.config
<rule name="Block contact form spam" stopProcessing="true">
<match url="(.*)" ignoreCase="true" />
<conditions logicalGrouping="MatchAll">
<add input="{URL}" pattern="/xmlrpc.php" ignoreCase="true" negate="false" />
<add input="{REQUEST_METHOD}" pattern="POST" ignoreCase="true" negate="false" />
</conditions>
<action type="CustomResponse" statusCode="403" statusReason="Forbidden" statusDescription="Forbidden" />
</rule>
Update: renamed "whitelist" to "allow list".
Conclusion and giveaway
This isn't the first post on Sysadmins of the North about XML-RPC, blocking access to a file, securing WordPress or .htaccess/web.config files. Check out these gems:
/posts/disallow-direct-access-to-php-files-in-wp-content-uploads/
/posts/wordpress-htaccess-security-best-practices-apache-24/