作者:騰訊科恩實驗室
公眾號:https://mp.weixin.qq.com/s/SgY1QsPmgU8iI4EUJfhznQ

6月12日,由騰訊安全發起,騰訊安全科恩實驗室與騰訊安全平臺部聯合主辦,騰訊安全學院協辦的2019騰訊安全國際技術峰會(TenSec 2019)在上海西岸藝術中心召開。

騰訊安全科恩實驗室兩位安全研究員Marco Grassi和陳星宇透過對VirtualBox的架構設計及攻擊面和虛擬機逃逸漏洞利用過程的分析,總結并首度發布了云計算和桌面虛擬化技術的最新漏洞發現,以下是漏洞分析詳情。

01 背景介紹

QEMU(Quick Emulator)是一款免費的開源模擬器,可以用來執行硬件虛擬化。

它通過動態二進制轉換模擬機器的處理器,并為機器提供一組不同的硬件和設備模型, 使其能夠運行于各種客戶操作系統。 它還可以與KVM一起使用,以接近本機的速度運行虛擬機(通過利用Intel VT-x 等硬件擴展)。 QEMU還可以對用戶級進程進行仿真,允許某個架構編譯的應用程序在另一個架構上運行。

SLiRP模塊主要模擬了網絡應用層協議,其中包括IP協議(v4和v6)、DHCP協議、ARP協議等,在sourceforge上有 一個很古老的版本源碼,QEMU源碼中的slirp代碼和這里的十分相似。引人注意的是,slirp模塊很久未做修改,但是他是QEMU中默認的網絡模塊,所以其安全性很值得研究。

02 漏洞成因與細節

在模擬tcp協議時,slirp中對幾個特別的端口進行了特殊處理,其中包括端口113(Identi?cation protocol),21(ftp), 544(kshell),6667 6668(IRC)……在處理這些特殊的端口時,需要對用戶數據進行操作,一不小心就會出現問題。 CVE-2019-6778就是slirp處理113端口的tcp請求時,未驗證bu?er剩余空間是否足夠,直接拷貝用戶數據導致的堆溢出。

slirp模塊中有兩個重要的數據結構,一個是mbuf,一個是sbuf,mbuf是存儲用戶從ip層傳入的數據的結構,而sbuf是存儲tcp層中數據的結構體。他們的定義分別如下:

可以看到在模擬ident協議時,程序拷貝了mbuf中的用戶data至sbuf中,同時將sb_wptr和sb_rptr向后加上拷貝的字節數,但是這里程序并未對sb_cc進行任何的操作,在上一層的函數的驗證,

在調用tcp_emu之前,會驗證sbuf中的剩余空間是否足夠,但是由于在模擬ident協議時拷貝了數據卻并未加上相應的長度進sb_cc,這樣使得sbspace計算出來的空間并不是sbuf實際的剩余空間。

所以如果用戶一直向113端口發送數據的話,那就會造成在sbuf中的溢出。

poc如下:

在host中運行 sudo nc -lvv 113 ,再在guest中運行poc中即可。注意這里不一定要連接host,只要任何guest可以連接的IP都可以。

03 漏洞利用

由于溢出發生處是在一塊純bu?er,前后的數據在實際運行中都是不穩定的,所以需要一個適當的手段來控制堆。

Malloc Primitive

IP分片(IP fragmentation)

IP fragmentation is an Internet Protocol (IP) process that breaks packets into smaller pieces (fragments), so that the resulting pieces can pass through a link with a smaller maximum transmission unit(MTU) than the original packet size. The fragments are reassembled by the receiving host.

在IPv4中,IP分片存在于兩個mtu不一樣的網絡之間傳輸數據,如果一個較大的packet想傳輸到一個mtu較小的網絡中,那么就需要將這個packet分片后再發送,在IP頭中就有專門的字段來滿足這一需求。

  • Zero (1 bit),為0,不使用。

  • Do not fragment ?ag (1 bit),表示這個packet是否為分片的。

  • More fragments following ?ag (1 bit),表示這是后續還有沒有包,即此包是否為分片序列中的最后一個。

  • Fragmentation o?set (13 bits),表示此包數據在重組時的偏移。

在試圖重組ip包時,如果重組函數返回NULL,這表示當前的分片序列并沒有結束,這樣這個包就不會被接下來的流程處理,而會直接return!

這意味著我們可以在內存中任意分配IP包(也就是mbuf),這將是一個非常好的malloc原語(primitive)。

Infoleak

想要任意地址寫的前提是我們需要一個leak。好消息是由于溢出的字節數是我們可以控制,因此我們可以修改地址的低位。leak的計劃就將是:

  1. 溢出修改m_data的低位,在堆的前面寫入一個偽造的ICMP包頭;

  2. 發送一個ICMP請求,將MF bit置位(1);

  3. 第二次溢出修改第二步的m_data的低位至偽造的包頭地址;

  4. 發送MF bit為0的包結束ICMP請求;

  5. 接收來自host的ICMP返回包。

這樣完成了infoleak,我們可以得到qemu-system的基址以及slirp所使用的堆基址。

Control PC

現在的問題轉化為,在已知基址的情況下,如何利用任意地址寫對程序執行流的控制?

最終,在全局段上找到了我們的目標對象:QEMUTime。

在QEMUTimer中,expire_time時間到了以后,將會執行cb(opaque)。

04 漏洞危害

該模塊是QEMU中的默認網絡后端(Backend),攻擊者利用該漏洞可以導致虛擬機拒絕服務,宿主機crash,嚴重者可造成在宿主機上的任意命令執行。

普通用戶可能會受此漏洞影響,而云服務商大多使用Virt I/O,故不受此漏洞影響。

05 漏洞修復

漏洞詳情可見Redhat安全社區:

https://bugzilla.redhat.com/show_bug.cgi?id=1664205

漏洞修復如圖所示,在拷貝數據前驗證sbuf中剩余空間是否足夠,目前QEMU最新版已修復該漏洞。


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