What is a best way to eliminate xmlrpc.php file from WordPress when you don't need it?
9 Answers
Since WordPress 3.5 this option (XML-RPC
) is enabled by default, and the ability to turn it off from WordPress dashboard
is gone.
Add this code snippet for use in functions.php
:
// Disable use XML-RPC
add_filter( 'xmlrpc_enabled', '__return_false' );
// Disable X-Pingback to header
add_filter( 'wp_headers', 'disable_x_pingback' );
function disable_x_pingback( $headers ) {
unset( $headers['X-Pingback'] );
return $headers;
}
Although it does what it says, it can get intensive when a site is under attack by hitting it.
You may better off using following code snippet in your .htaccess
file.
# Block WordPress xmlrpc.php requests
<Files xmlrpc.php>
order allow,deny
deny from all
</Files>
Or use this to disable access to the xmlrpc.php
file from NGINX server block.
# nginx block xmlrpc.php requests
location /xmlrpc.php {
deny all;
}
Be aware that disabling also can have impact on logins through mobile. If I am correct WordPress mobile app does need this.
See Codex for more information about the use ofXML-RPC
.
- Please make always a backup of the file(s) before edit/add.
Edit/Update
@Prosti, -You are absolutely correct- about the options which RESTful API
will offer for WordPress!
I forgot to mention this. It should already have been integrated into core (WordPress version 4.1) which was not possible at that time. But as it seems, will be core in WordPress 4.5 .
The alternative for the moment is this plugin: WordPress REST API (Version 2)
You can use it till Restful API
is also core for WordPress.
Target date for release of WordPress 4.5. (April 12, 2016 (+3w))
For those who are interested in
RESTful
, on Stackoverflow is a very nice community wiki.
-
2If I am correct WordPress mobile app does need this - probable this will not be needed in the future once we have transition to WordPress RESTful API (WordPress 4.5)– prostiMar 4, 2016 at 7:55
-
2For those who still get
X-Pingback
header for single post/page. We need to use another filter to remove it completely:add_filter('pings_open', '__return_false', PHP_INT_MAX);
.– wpclevelAug 10, 2016 at 17:02 -
1Adding things like that to
functions.php
will lose all effect when changing themes.function.php
is only for design purposes, use a plugin!– DavidSep 20, 2016 at 11:07 -
@David, sure but ppl then better use mu-plugins folder, instead of making for such a plugin. When ppl need/use a function like this they have that for a reason and do not want anyone (not even an admin) to have the option to de-activate a plugin.– CharlesSep 20, 2016 at 16:14
-
Looks like there is an equals sign (
=
) missing in first line of the nginx conf code there. This worked for me:location = /xmlrpc.php {
– DaveFeb 7, 2017 at 19:45
When you have the ability to block it via your web server's configuration, @Charles' suggestions are good.
If you can only disable it using php, the xmlrpc_enabled
filter is not the right way.
Like documented here:
https://developer.wordpress.org/reference/hooks/xmlrpc_enabled/
it only disables xml rpc methods that require authentication.
Instead use the xmlrpc_methods
filter to disable all methods:
<?php
// Disable all xml-rpc endpoints
add_filter('xmlrpc_methods', function () {
return [];
}, PHP_INT_MAX);
You can test if it's working by sending a POST request to xmlrpc.php with the following content:
<methodCall>
<methodName>system.listMethods</methodName>
</methodCall>
If the filter is working, there should only be 3 methods left:
<?xml version="1.0" encoding="UTF-8"?>
<methodResponse>
<params>
<param>
<value>
<array>
<data>
<value>
<string>system.multicall</string>
</value>
<value>
<string>system.listMethods</string>
</value>
<value>
<string>system.getCapabilities</string>
</value>
</data>
</array>
</value>
</param>
</params>
</methodResponse>
you can quickly test it with curl:
curl -X POST \
-H 'Cache-Control: no-cache' \
-H 'Content-Type: application/xml' \
-d '<methodCall><methodName>system.listMethods</methodName></methodCall>' \
https://your-wordpress-site.com/xmlrpc.php
We are using the htaccess file to protect it from hackers.
# BEGIN protect xmlrpc.php
<files xmlrpc.php>
order allow,deny
deny from all
</files>
# END protect xmlrpc.php
The best thing to do is disable xmlrpc.php
functions with a plugin rather than delete or disable the file itself. The file itself will be replaced on WordPress core updates, while a plugin will keep it disabled after core updates and if you change themes.
See https://wordpress.org/plugins/search.php?q=disable+xml-rpc for different plugins. They all have minor differences.
These plugins do the same thing as a function added to the theme's functions.php
file or adding an order,allow deny
rule to .htaccess (as outlined in other answers), with the difference being a plugin or function disables calls to xmlrpc.php
via PHP, and the rule in .htaccess works by leveraging mod_rewrite in the webserver (i.e., Apache or Nginx). There is no appreciable performance difference between using PHP and mod_rewrite on a modern server.
For the extreme minority that are hosting WordPress in IIS, you could use the IIS URL Rewrite module to do similar htaccess-like restrictions. The example below assumes the true client IP is coming in the X-Forwarded-For header, the known whitelist IP is 55.55.555.555, and that you want to respond with an HTTP 404 to non-whitelist IPs.
<rule name="wordpress-restrictions" enabled="true" stopProcessing="true">
<match url="(^xmlrpc.php)|(^wp-admin)|(^wp-login.php)" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="false">
<add input="{HTTP_X_FORWARDED_FOR}" pattern="(^55\.55\.555\.555$)" negate="true" />
</conditions>
<action type="CustomResponse" statusCode="404" subStatusCode="44" statusReason="File or directory not found" statusDescription="The resource you are looking for might have been removed, had its name changed, or is temporarily unavailable." />
</rule>
The best way is to use .htaccess file to block all requests by adding
# Block WordPress xmlrpc.php requests
<Files xmlrpc.php>
order deny,allow
deny from all
allow from 1.1.1.1
</Files>
to the end of the file but if you want the easiest way using Disable XML-RPC-API plugin will do the job.
I have recently installed Wordfence which, as of version 6.3.12 has the ability to block direct access to any location. Putting /xmlrpc.php onto the Options page in the list of banned access IPs "Immediately block IPs that access these URLs" is now showing one attempt being blocked about every 15 minutes.
This also has the advantage of being able to block a URL to escape from those pesky bots that come back with a different IP address time and again.
I do not know if it allows the use of xmlrpc.php by Apps for valid operations.
I had some issues with it producing 504 Timeout and 502 Bad Gateway errors on the server at first but it seems to have settled down.
Very impressed with the result so far and it produced a valuable cleanup profile after the site had been hacked before installing Wordfence and despite always having the latest version of WordPress and plugins.
-
Adding
/xmlrpc.php
to a security rule banning IPs that access it seems like it could block legitimate traffic. If a site with pingbacks enabled links to your site, that site will send a request to that URL and immediately become blocked...seems like it could cause problems. Sep 22, 2017 at 18:38
i use for nginx this small Code and this works 100%
location ~* (/wp-content/.*\.php|/wp-includes/.*\.php|/xmlrpc\.php$|/(?:uploads|files)/.*\.php$) {
deny all;
access_log off;
log_not_found off;
return 444;
}
Using a Security Plugin (Recommended):
One of the easiest ways to block access to xmlrpc.php in WordPress is by using a security plugin like Wordfence
or Sucuri Security
. These plugins often have options to block XML-RPC or specific files like xmlrpc.php.
Using Server-Side Rules Apache
<Files xmlrpc.php>
Order Deny,Allow
Deny from all
</Files>
Using Server-Side Rules Nginx
location ~* /xmlrpc.php {
deny all;
access_log off;
log_not_found off;
}
Reload your nginx
sudo systemctl reload nginx
Disable XML-RPC via wp-config.php:
define('XMLRPC_REQUEST', false);