You've probably never heard of XML-RPC.  But I can almost guarantee you've used it.

If you're a WordPress fan like me, and you've ever used one of the mobile apps to publish, check comments, or view your stats, then you've used XML-RPC.  If you've used Microsoft Word or any of the plethora of desktop blogging apps to write to your site, you've used XML-RPC.  If you've ever installed and activated the Jetpack plugin, then you've used XML-RPC.[ref]I want to quickly point out that Jetpack itself never exposes your username or password. I inky mention the plugin as an example of how you might already be using XML-RPC; even if you've never heard of it.[/ref]

My point: it's everywhere.

XML-RPC is Insecure

By itself, I would allege that WordPress' XML-RPC interface is the most insecure part of the platform.  Not due to the way it's designed - the interface is just as secure as the rest of the product - but in the way it's used.

Every request is authenticated on the user level - meaning you are logging back in to your site every time you send off a request to it.  You've probably never profiled a remote interaction with your site; I have, and it's frightening.

I sometimes write posts using Windows Live Writer, a popular desktop blogging app for Windows.  Whenever it pushes content out to my site, it runs through a total of 4 XML-RPC requests.  One to send the content, one to send tags, one to send categories, and one to verify the post is published as intended.  If I add media to a post, there are even more requests created.

Why is this bad? Because every request contains both my username and my password. In plain text.

Every time you pull out your phone to check you blog stats, you're sending your username and password across the wire.  Every time you moderate a comment.  Every time you jot down a quick post title.  Every time you refresh a post status.  Your username. Your password. Out there for the world to see.

If we all browsed the Internet exclusively over HTTPs, this wouldn't be an issue.  I don't want to configure (and pay for) an SSL certificate just so I can blog on my personal site.  Many of you likely feel the same way; all of us are vulnerable to being hacked as a result.[ref]I'm using harsh, scary language here to make a point.  Truthfully, if you're on a private, home network or using a mobile app over a 4G network you are much more secure.  It's only when you're on coffee shop WiFi or some other open network when things become vulnerable.  In that situation, there's little you can do to make things safer - so I'd suggest buying an SSL certificate or investing in a VPN if open networks are your sole means of connecting to the Internet.[/ref]

A Way Forward

I'm working on a few newer XML-RPC-based applications, and the thought of having usernames and password spewed out on the net for the world to see worries me.  I've taken the time to come up with a more secure method for WordPress apps and users to use XML-RPC, and today I want to share it with you.

Today I'm introducing Secure XML-RPC, an experimental plugin for WordPress.  This plugin sits atop WordPress' standard XML-RPC implementation, remains 100% backwards compatible, but extends a new method for authenticating without exposing your sensitive information to the world.

How It Works

Once you're logged in to WordPress, you have access to a new section on your profile: "Remote Publishing Permissions."  This section lists out any applications that have permission to interact with WordPress on your behalf, along with their public and secret keys.

You will take both of these keys and give them to your application (the client) - be it a desktop program, an Android app, a remote webpage, whatever.

When the client wants to send a request, it will build the XML document it normally builds (leaving the username and password fields blank).  Then it will create a SHA256 hash of its secret key and the XML document.  The client will then pass its public key and this hash in the [cci]Authorization[/cci] header of the request to WordPress.

WordPress will, in turn, use the client's public key to look up the user with whom it is associated.  WordPress will then independently compute the SHA256 hash of the secret key + request document and compare it to the hash provided in the request.  If they match, then we have an authentic request and things move forward.

Why It Works

Both username/password authentication and public/secret key authentication work on a simple principal - there is some secret information shared by both the client and the server that's used to authenticate a request.  In password-based authentication (at least with WordPress), this secret information has to be sent to the server for verification - which means it's no longer secret.

With key-based authentication, the secret key is never sent across the wire.  Someone intercepting the request can't pretend to be the user in order to make a different request since the [cci]Authorization[/cci] hash is dependent both on the secret key and the body of the request.  While key-based authentication won't protect against replay attacks (password-based authentication won't either), it does protect against impersonation and request forgery.

How You Can Help

As the use of WordPress grows worldwide, the need for more sophisticated security is obvious.  Key-based authentication can be applied to any sort of API exposed by WordPress, so even if you think XML-RPC is antiquated, you can still help validate the model so we can apply it elsewhere.

What we need now is involvement and contribution.  We need testers.  We need proof-of-concept apps that use the new authentication model.  We need UX attention on the administrative interfaces.  We need devils' advocates pointing out the flaws in the system so it can be improved.

I want to see non-password-based authentication in WordPress core.  If not in the next version, then at least in the near-term foreseeable future.  You can submit pull requests or issues on GitHub.  You can discuss the idea in the comments below.  You can install the plugin on your own site and give it a whirl.

Let's work together to make better security a reality.