HTTP.sys遠程執行代碼漏洞

遠程執行代碼漏洞存在於 HTTP 協議堆棧 (HTTP.sys) 中,當 HTTP.sys 未正確分析經特殊設計的 HTTP 請求時會致使此漏洞。html

http://bbs.safedog.cn/thread-78756-1-1.html安全

 

HTTP.SYS遠程執行代碼漏洞分析 (MS15-034 )

 

   

 

 

 


寫在前言:

      在2015年4月安全補丁日,微軟發佈了11項安全更新,共修復了包括Microsoft Windows、Internet Explorer、Office、.NET Framework、Server軟件、Office Services和Web Apps中存在的26個安全漏洞。其中就修復了HTTP.sys 中一處容許遠程執行代碼漏洞,編號爲:CVE-2015-1635(MS15-034 )。目前服務器安全狗已經更新了安全補丁,建議及時修復安全狗提示給您的漏洞信息,以避免漏洞被利用遭到攻擊。



      據稱,利用HTTP.sys的安全漏洞,攻擊者只須要發送惡意的http請求數據包,就可能遠程讀取IIS服務器的內存數據,或使服務器系統藍屏崩潰。

      根據公告顯示,該漏洞對服務器系統形成了不小的影響,主要影響了包括Windows 七、Windows Server 2008 R二、Windows 八、Windows Server 20十二、Windows 8.1 和 Windows Server 2012 R2在內的主流服務器操做系統。

       安全狗安全研究團隊的小夥伴們在得知這一漏洞狀況後,也對其進行了深刻挖掘研究,下面就將相關信息結果分享給你們。若是有任何想法,以及進一步的利用操做,也歡迎指教討論。

1. 首先對補丁文件作了二進制比對

如下是Windows 7 修復先後HTTP.SYS的變化。



值得注意的經驗是,每一個函數名中都有’range’。 這不由讓我想起了以前Apache HTTPd ‘Range’ 頭漏洞, (參見RFC2616章14.35節)。

漏洞數據由 ‘range’ 頭帶入已經毋庸置疑。 下面要作的是深刻研究其產生的緣由。如IDA 自動分析出的的HTTP!UlpParseRange 函數的調用關係圖所示:



這裏我使用Vmware搭建了一個未打補丁的Windows 7 SP1 做爲測試目標,而且啓用了內核調試器, 對全部關鍵函數設置斷點,收集關鍵數據和內核信息。



在斷點被觸發以後, 堆棧信息會被打印出來, 接着程序繼續執行.  咱們使用了以前的Apache Rangedos 測試樣本針對目標服務器作了攻擊性測試, 調試器捕獲到了下面這些信息:



標準的Apache RangeDos 腳本確實產生了效果,下面讓咱們更進一步的來看一下 HTTP!UlpParseRange 函數的實現:


在舊代碼的調試中發現函數在此處調用了一個很大的整數。



而新版本的代碼 調用了HTTP!RtlULongLongAdd 來檢查是否有整數溢出。 注意,這個HTTP.sys內的函數調用5個參數而不是3個參數。重複以前的測試腳本, 就會發現系統返回的錯誤代碼是0xC000000D(STATUS_INVALID_PARAMETER),而再也不是 STATUS_INTEGER_OVERFLOW 。

修正以後的一個簡單的POC測試腳本以下(此腳本僅用來解析證實模塊內部對Range頭參數的解析過程)。



接着讓咱們在未打補丁的模塊上下斷點。



很是明顯了。 EAX 是0x7A69 (Poc中設置的range上限 31337), EDI 是0x539(Poc中設置的range下限 1337)。 在老代碼中,若是咱們的下限是0,則上限不會作如此的改變。在上限很是大的時候(整數臨界值), 咱們加1, 就會發生整數溢出。 HexRays 的輸出更加明瞭:
*(_QWORD *)v18 = __PAIR__(v22, v23) – __PAIR__(v21, v20) + 1.讓咱們來試試看。



這時候能夠看到上限已經很是的大了(0xFFFFFFFF)。代碼接着執行。



We can see that EAX is predictably small now.  Now that we have some indication of what the pre-patch block is doing, let’s look at the patch again.

最後EAX在加1以後溢出變成了0. 讓咱們再看看打過補丁的模塊:



使用一樣的手法, 咱們獲得了一個不一樣的錯誤信息. 有趣的是不少狀況下都會產生這個錯誤信息(好比節點深度問題等)。可是咱們的主要目標是判斷是否打補丁, 因此這個沒什麼大礙. 如今讓咱們回到系統是否打補丁的預判上.

一種方法讓未打補丁的模塊返回STATUS_INVALID_PARAMETER錯誤信息的方法就是使下面代碼的關鍵處校驗失敗。



使用調試器動態改變跳轉條件, 咱們可讓服務器返回下面這個有趣的頁面(手工內存補丁成功)



打完補丁之後當你提交了包含非法range頭字段的http包的時候, 系統會報上面的錯誤。

若是沒打補丁你看到的就是下面這樣:


這就是判斷是否打了補丁的關鍵.
 

打了補丁:  HTTP!RtlULongLongAdd在遇到非法range頭的時候會返回一個 STATUS_INVALID_PARAMETER 錯誤, 接着HTTP!UlpParseRang 產生一個」Invalid Header」 錯誤信息給客戶端.  

打了補丁:  HTTP!UlpParseRange 返回 0, 接着產生一個 「Requested Range Not Satisfiable」.錯誤信息給客戶端.
 
二、漏洞測試腳本:
 
    #sutff.py
    import socket
    import random

    ipAddr = "這裏填入檢測IP地址"
    hexAllFfff = "18446744073709551615"

    req1 = "GET / HTTP/1.0\r\n\r\n"
    req = "GET / HTTP/1.1\r\nHost: stuff\r\nRange: bytes=0-" + hexAllFfff + "\r\n\r\n"

    print "[*] Audit Started"
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    client_socket.connect((ipAddr, 80))
    client_socket.send(req1)
    boringResp = client_socket.recv(1024)
    if "Microsoft" not in boringResp:
                    print "[*] Not IIS"
                    exit(0)
    client_socket.close()
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    client_socket.connect((ipAddr, 80))
    client_socket.send(req)
    goodResp = client_socket.recv(1024)
    if "Requested Range Not Satisfiable" in goodResp:
                    print "[!!] Looks VULN"
    elif " The request has an invalid header name" in goodResp:
                    print "[*] Looks Patched"
    else:
                        print "[*] Unexpected response, cannot discern patch status"

 

一個簡單的檢測方法:

curl http://xxx.com/ -H "Host: irrelevant" -H "Range: bytes=0-18446744073709551615"|grep "range is not satisfiable"
有發現 返回」range is not satisfiable」就說明有漏洞了.
 


三、修復方法

(1)下載安裝最新版服務器安全狗

選擇服務器優化-->系統漏洞修復-->修復漏洞.

 




(2)開啓網站安全狗實時防禦功能,實時防禦服務器網站安全




 
安全狗下載地址:www.safedog.cn

微軟報告:
https://technet.microsoft.com/en-us/library/security/MS15-034

相關鏈接
http://blog.beyondtrust.com/the-delicate-art-of-remote-checks-a-glance-into-ms15-034
相關文章
相關標籤/搜索