作者:LR、noirfate
Qemu是一款處理器模擬軟件,可以提供用戶模式模擬和系統模式模擬。當處于用戶模式模擬狀態時,將使用動態翻譯技術,允許一個cpu構建的進程在另一個cpu上執行。
VNC [ Virtual Network Computing ]是一款優秀的遠程控制工具軟件。由于Qemu內置vnc功能模塊,所以可通過vnc客戶端對遠程Qemu虛擬機進行遠程訪問。
360安全團隊的 連一漢 在閱讀Qemu-VNC源碼過程中,發現了功能模塊中的一個遠程拒絕服務,漏洞危險等級為中,漏洞編號CVE-2015-5239。
相關信息見 https://access.redhat.com/security/cve/CVE-2015-5239
VNC采用RFB通信協議。RFB ("remote 幀緩存 ") 是一個遠程圖形用戶的簡單協議。通過這個協議,用戶可以遠程模擬鼠標點擊、鍵盤按鍵以及文本復制/剪切等功能。本文所講述漏洞就是在文本復制/剪切時觸發的。詳細協議格式如下圖:
舉例說明:
下面這段數據是真實發送的用于文本復制/剪切的報文。
06 00 00 00 00 00 00 06 74 65 73 74 21 21
06 :表示協議類型message-type
00 00 00 :用于填充padding
00 00 00 06 :待剪切數據的長度length
74 65 73 74 21 21:待剪切數據內容text
協議格式相對簡單,就不再進一步描述。
QEMU在通過vnc讀取報文中存儲的剪切板中的數據時,由于其未對報文中用于描述數據長度的字段進行嚴格限制,進而導致其出現邏輯錯誤進入死循環。下面就是程序處理的主體邏輯:
a) 讀取報文中用于描述待讀取數據長度的字段
b) 判斷這個字段是否超過整個報文的長度。
c) 如果為否,則進行數據復制;如果為是,則跳出循環
實現代碼如下(ui/vnc.c):
從上述代碼中可以發現:由于len的初始值為1,所以protocol_client_msg()
的返回值為8。Input.offset
的值始終為14大于8,所以此時不會跳出循環。在進入下次循環時8將作為protocol_client_msg()
的參數len傳入,用于讀取報文長度字段的值。但是,如果此時讀取的報文中的長度字段為0xFFFFFFF9
則protocol_client_msg()
的返回值又將為1,下次循環時len的值也就又恢復為初始值1。這樣,程序又進入開始時的狀態,再次調用protocol_client_msg()
并且返回值為8。然后又將8傳入protocol_client_msg()
,讀取報文中的長度字段0xFFFFFFF9
,返回值又為1,循環往復。由于在這段循環過程中客戶端連接標志vs->csock
始終未被更改,程序也將無法跳出循環,從而進入死循環狀態。Vnc拒絕服務也就由此產生。
攻擊者利用該漏洞可以導致虛擬機拒絕服務,并且保持對cpu的高占用率,繼而會影響宿主機以及其他虛擬機的正常執行。 我們在測試環境中對該漏洞進行測試,觸發前后的截圖如下。可以看到,在漏洞觸發后qemu-kvm無法遠程訪問,并占有極高的CPU使用率,嚴重影響其它程序的運行。 漏洞觸發前CPU的狀態:
漏洞觸發后CPU的狀態:
官方對該漏洞的修補方法如下:
具體見:http://git.qemu.org/?p=qemu.git;a=commit;h=f9a70e79391f6d7c2a912d785239ee8effc1922d
該補丁中,開發人員對關鍵數據dlen的大小進行嚴格的大小判斷,確保數據長度值不能超過1MB。這樣就完美修復此漏洞。在這里建議所有使用qemu的廠商采用該補丁,防止攻擊者利用CVE-2015-5239漏洞對廠商和用戶攻擊造成損失。 建議廠商安排安全修復。