DiggingIntoWordPress

by Chris Coyier & Jeff Starr

The xmlrpc.php File and Site Security

Posted by on

Located in the header.php file of most WordPress themes, there is an important hook called wp_head(). This essential hook enables functions to output content to the browser in the <head> area of the web document 1. In newer versions of WordPress, this hook enables WordPress to output the following three lines to your theme’s <head> section 2:

<link rel="EditURI" type="application/rsd+xml" title="RSD" href="http://digwp.com/xmlrpc.php?rsd" />
<link rel="wlwmanifest" type="application/wlwmanifest+xml" href="http://digwp.com/wp-includes/wlwmanifest.xml" /> 
<link rel='index' title='Digging into WordPress' href='http://digwp.com/' />
<meta name="generator" content="WordPress 2.8" />

As you can see, lots of stuff is added, including feed links, XML-RPC and WLW links, and a couple of other items. While there is plenty to discuss with all of these inclusions, here we are concerned primarily with the link to the xmlrpc.php file. WordPress includes this link for its XML-RPC interface, which enables remote software applications to communicate and interact with WordPress.

What does the xmlrpc.php file do? Do I need it?

While documentation on WordPress’ XML-RPC is fairly thin, we can glean a partial understanding of how the xmlrpc.php works by stepping through the code in the file itself. Don’t worry, we’re not going to bore you with that here, but suffice it to say that the xmlrpc.php is required for the following types of activity:

  • Posting directly to your blog using TextMate, Flock, and other weblog clients
  • Posting directly to your blog using Eudora, Thunderbird, and other email apps
  • Receiving pingbacks and trackbacks to your site from other blogs

Not everyone uses the remote-posting functionality available to them in WordPress, but I think that many blogs are definitely using the XML-RPC protocol for the pingback and trackback functionality.

Does the xmlrpc.php file pose a security risk?

Some of you may remember the security risk associated with the xmlrpc.php script back in the good ‘ol days of WordPress 2.1.2, whereby:

WordPress could allow a remote authenticated attacker to bypass security restrictions, caused by improper validation by the xmlrpc.php script. A remote attacker with contributor permissions could exploit this vulnerability to publish posts to the Web site.

This vulnerability was promptly eliminated in version 2.1.3, but shortly thereafter (in version 2.3.1) another security issue was discovered when the XML-RPC implementation was found to leak information. Although this was fixed in version 2.3.2, the security concerns associated with the XML-RPC protocol eventually led the WordPress devs to disable remote access by default in version 2.6 3. The xmlrpc.php file is still included in the document <head> (presumably for the sake of pingbacks and trackbacks), but the remote-access functionality is non-operational until explicitly enabled 3.

Security tips for your site’s xmlrpc.php file

At the time of this writing, there are no known vulnerabilities associated with WordPress’ XML-RPC protocol. Even so, there have been security issues with the xmlrpc.php script in the past, and there could certainly exist new problems both now and in the future. Just to be on the safe side, here are a few different strategies and tips to help ensure maximum security for your blog.

If you don’t need it, delete it
Perhaps the safest way to eliminate potential security vulnerabilities is to simply remove the script in question. If you have no need for remote-posting, pingbacks or trackbacks, it may be easiest to simply remove the xmlrpc.php file from your server. Instead of actually deleting it, you may just want to rename it something unguessable. Either way, if the script isn’t available to an attacker, it makes it hard to exploit.

Update: If you remove (or rename) the xmlrpc.php file from your WordPress installation, you should also implement the function described in the next section to avoid an avalanche of 404 errors (see this comment for further explanation).

Remove the links to xmlrpc.php and wlwmanifest.xml
Alternately, if you aren’t needing any remote-access or pingback functionality, you may prefer to simply remove the associated header links rather than deleting any core files from your server. This is easily accomplished with the following function placed in your active theme’s functions.php file:

function removeHeadLinks() {
	remove_action('wp_head', 'rsd_link');
	remove_action('wp_head', 'wlwmanifest_link');
}
add_action('init', 'removeHeadLinks');

This will prevent these two files from being linked to in the header, but the files themselves will remain available on your server. Definitely make sure that the default disabling of remote publishing in effect if you implement this method.

Disable the remote-publishing functionality
If you don’t remote-publish, but you still want to receive pingbacks and trackbacks, take WordPress’ advice and just leave the remote-access functionality disabled by default. This step alone seems like a tremendous way to help tighten down your blog’s security. The file will still be available on your server, but attackers will be able to do much less with it.

Prevent malicious xmlrpc.php directory scanning
For those of you who wisely keep an eye on your server access and error logs, you have likely seen a recent surge in the amount of malicious xmlrpc.php directory scanning. For whatever reason, the bad guys are suddenly very interested in xmlrpc.php files, and are scanning every directory they can get their bots on trying to locate them. I have seen tons of this kind of activity lately:

http://domain.tld/2009/xmlrpc.php
http://domain.tld/2009/06/xmlrpc.php
http://domain.tld/2009/06/01/xmlrpc.php
http://domain.tld/2009/06/01/permalink/xmlrpc.php
http://domain.tld/2009/06/02/permalink/xmlrpc.php
http://domain.tld/2009/06/03/permalink/xmlrpc.php
.
.
.

Whether the attackers locate their target or not, this kind of behavior drains system resources, hogs bandwidth, and prevents your site from operating at maximum capacity. Thus, to prevent this malicious behavior from damaging your site, I have devised the following HTAccess solution:

<IfModule mod_alias.c>
RedirectMatch 301 /(.*)/xmlrpc\.php$ http://domain.tld/xmlrpc.php
</IfModule>

When placed in the web-accessible root HTAccess file for your site, this simple directive will redirect all requests for your blog’s xmlrpc.php file to the actual file. I have been using this method for several weeks now at Perishable Press and have eliminated thousands of misdirected requests because of it.

Leave the xmlrpc.php file but prevent access to it
Last but not least is a simple method enabling you to leave the file in place on your server but prevent access to it. Perfect if you don’t need the script and want to be as lazy as possible about keeping it secure (think no maintenance). Simply paste the following code into your root HTAccess file and be done with it:

<IfModule mod_alias.c>
RedirectMatch 403 /(.*)/xmlrpc\.php$
</IfModule>

1 Or anywhere the wp_head() hook is located.
2 Working with WordPress version 2.8 at the time of this writing.
3 To enable this feature, go to “Settings > Writing > Remote Publishing” in the WP Admin

12 Responses

  1. Daniel Groves June 24, 2009

    Thanks for this Jeff! I will certainly be thinking about this when designing all future website designs as I tend to use wordpress as a CMS for just about everything these days!

  2. Since I don’t really use pingbacks/trackbacks on CSS-Tricks (too much spam garbage, and I don’t like how it’s WordPress specific). I just rolled this out.

    I chucked the file (backed it up just in case), and put in the new functions.php stuff. So I can still safely still use the wp_head call.

    • Good point, Chris — I am updating the article to recommend that the functions.php method be used whenever the xmlrpc.php file is removed (or renamed) from the installation. Otherwise there would be a ton of 404 errors for the missing file.

  3. Nice article. You mention that we should be checking our access logs for security. I’m an amature webmaster and I don’t have a clue what to look for in an access log. It would be great if you could cover this in a video tutorial one day.

    • That is an excellent idea, David – I think that would be a very useful topic to cover here at DiW. I’ll add it to the list! Cheers.

  4. A good post! The explain is very clear. I like the remove_action() methods, and the redirect :).

    Thank you very much.

  5. Perhaps I’m misunderstanding but I added the suggested code to my functions.php and renamed xmlrpc.php. After doing that I get a blank white page. I’m assuming there is a PHP error somewhere. This was done on a fresh WP 2.8 install using MAMP

    • Are you referring to the removeHeadLinks() function? If so, not sure what the issue could be, perhaps you may want to test it on a non-local server?

      • Yep. I noticed that whether or not I called that function it was breaking other stuff in the admin section as well. I may have just done something wrong. Once I removed it everything started working again. I’ll try it again on my public server when I get the rest of the site built out.

  6. Great post! I’m going to apply these modifications in all of my blogs / websites based on WordPress.

    By leaving the xmlrpc.php file on the server but prevent access to it we could always chmod 000 :)

Comments are closed. Contact us with any critical information. Thank you!

Code is poetry