How to Gain Control of WordPress by Exploiting XML-RPC
WordPress did not become what is arguably the most popular blogging and CMS platform on the planet because it was difficult to use. Rather, its user-friendly and rich feature set led to it finding a home on somewhere north of 70 million websites—and that's just counting blogs hosted on WordPress.com.
Today, we're interested in the platform's use of XML-RPC, a remote procedure call (RPC) allowing for encoded XML calls that are transported via the HTTP protocol. This makes it very, very easy for WordPress contributors to post content remotely, and makes it trivial to post a large volume of data in a one-time push.
But that ability to push a large amount of data means that we hackers can also push a large number of passwords at it. Sure, you're essentially brute-forcing your way into someone's WordPress account, but those 500 tries just look like you fat-fingered your password once. Two times? You just tried a thousand passwords. This sure beats trying one password per login attempt.
This exploit first turned up in September, 2015, and is one of many that went through XML-RPC. WordPress is good with patching these types of exploits, so many installs from WordPress 4.4.1 onward are now immune to this hack. However, you know a large number of those 70+ million are either older versions or unpatched—and are vulnerable to your password file. Let's get started.
First, if you've got WordPress running locally or on a virtual machine, you should check out the base install directory. We're interested in the xmlrpc.php file you might see there, because that mean's it's open to this attack.
You can also just try your site, followed by /xmlrpc.php, like I did below on my local WordPress (substitute "localhost" with your URL name for websites). If XML-RPC is listening, or is there, it will tell you so. Looks like we found a potentially vulnerable blog (it would say "forbidden" or something like that otherwise).
Without getting too deep into the weeds, XML-RPC works with the WordPress system.multicall functionality, which hints at the way you can direct a lot of information at the site at one time, say during content upload or retrieval of all recent posts.
This exploit takes advantage of the way content or, in this case, passwords are thrown at the login in great numbers without raising too many eyebrows. Logging in one time, WP is just passing an XML file with a string for your login name and a string for your password.
When you attempt to log into WordPress, your username/passwords are tracked as follows:
It's one-to-one, in other words. You might notice if someone was trying to log in every few seconds for hours, or you might have a tool set up to restrict incorrect logins. That's all sensible WordPress security. But concerning this article, if you combine XML-RPC with system.multicall, you can essentially throw hundreds of logins at WordPress concurrently, but only have those login attempts show as one login as above. This would raise no flags, right?
That's all we're trying to do here.
Below is an example of how this looks in XML format. The highlighted section is just one password try, so you'd have to repeat that section for multiple tries with different passwords. As you can imagine, this would take a serious amount of time doing them one by one.
To speed up this process, we're going to use a script found on GitHub that reads our password list and auto loops the highlighted section above with a new password from the password list in each section. So, head to the 1N3/Wordpress-XMLRPC-Brute-Force-Exploit on GitHub and download the files via the HTTP link. (Download the ZIP, or Git if you're into that.)
Open up a terminal window and cd to wherever you downloaded the file, then unzip the files in place:
Then change into that directory:
While you're in there, it won't hurt to change the permissions on the Python file to make sure we don't run into any problems running it. The "7" you're assigning means you will be able to do anything you want with the file.
chmod 755 wordpress-xmlrpc-brute.py
Now run the Python command alone, and check out the instructions.
I've highlighted the instructions in blue. For localhost, that's:
./wordpress-xmlrpc-brute.py http://localhost/xmlrpc.php passwords.txt username
In order, that means the Python file name, then server name, then password file name, and then username. Here, we're using the passwords.txt file included in the GitHub download (which only has a small amount of passwords in it), and we're trying admin as username. If you want to use your own password list, just include it in your command instead, and use whatever username you think appropriate—this tool only deals with the passwords.
So when you run the above with your target server name in place of "localhost," your password file, and your username, the Python script will run through the included passwords.txt file and will run in the largely undetected way. If successful, the script will spit out your login, in the form of username/password.
Guarding against the XML-RPC vulnerability is easy—newer versions don't include the functionality at all. That said, many third-party WordPress publishing tools such as Jetpack, and smart phone apps such as IFTTT, might require XML-RPC use, so even some current WordPress installs have been retrofitted with the vulnerable code and are therefore open to intrusion.
Check your own WordPress installs, and make sure that if integrating any new tool which allows interaction with WP from a remote standpoint, that you haven't opened the door to the XML-RPC intrusion or any other intrusions. This is one of many WordPress vulnerabilities, and this easy script attack is a good starting point into your research.