信息來(lái)源:FreeBuf
近日,Nettitude安全人員在Avast Virtualization內(nèi)核模式驅(qū)動(dòng)(aswSnx.sys)中發(fā)現(xiàn)一個(gè)安全漏洞,使用普通賬戶(hù)登錄的本地攻擊者可利用該漏洞提升權(quán)限,以系統(tǒng)權(quán)限執(zhí)行任意代碼,進(jìn)而完全控制受影響主機(jī)。
AvastVirtualization(aswSnx.sys)驅(qū)動(dòng)用于處理所有Avast Windows產(chǎn)品的“Sandbox”和“DeepScreen”功能。
受影響產(chǎn)品及版本
Avast InternetSecurity v11.1.2245
Avast ProAntivirus v11.1.2245
Avast Premierv11.1.2245
Avast FreeAntivirus v11.1.2245
上述產(chǎn)品中的早期版本也可能受到影響。
技術(shù)細(xì)節(jié)
AvastVirtualization內(nèi)核模式驅(qū)動(dòng)(aswSnx.sys)沒(méi)有驗(yàn)證用戶(hù)空間的IOCTL請(qǐng)求中的Unicode文件絕對(duì)路徑的長(zhǎng)度,而該路徑長(zhǎng)度會(huì)被復(fù)制到固定大小的分頁(yè)池內(nèi)存中,攻擊者可以借助特制的代碼導(dǎo)致內(nèi)核分頁(yè)池分配的數(shù)據(jù)塊溢出,并損壞其相鄰的攻擊者控制的內(nèi)核對(duì)象,如圖一。
圖一 攻擊者控制的內(nèi)核對(duì)象
圖二顯示了aswSnx.sys驅(qū)動(dòng)對(duì)nt!memmove函數(shù)的調(diào)用,但是這一過(guò)程沒(méi)有驗(yàn)證數(shù)據(jù)是否按可用大小被復(fù)制到分頁(yè)池的數(shù)據(jù)塊中。這些信息取自10.x版本,同樣適用于11.x版本。
圖二 漏洞原因
堆緩沖區(qū)溢出的利用
在處理基于緩沖區(qū)的動(dòng)態(tài)內(nèi)存分配,也就是基于堆的緩沖區(qū)溢出時(shí),首先需要預(yù)測(cè)緩沖區(qū)溢出發(fā)生的位置,以便于控制該漏洞的執(zhí)行。這在處理內(nèi)核地址空間的代碼運(yùn)行時(shí)是十分重要的,因?yàn)槿绻檬。到y(tǒng)可能會(huì)出現(xiàn)故障。損壞一個(gè)不可控制的隨機(jī)內(nèi)核對(duì)象實(shí)在不是一個(gè)明智的選擇。
為了達(dá)到這個(gè)目的,面臨的另一個(gè)挑戰(zhàn)就是,根據(jù)數(shù)據(jù)塊的大小創(chuàng)建一個(gè)合理的動(dòng)態(tài)內(nèi)存分配布局,用于溢出的產(chǎn)生。如果已知數(shù)據(jù)塊的大小,那么我們就可以沒(méi)有更多限制的實(shí)現(xiàn)這個(gè)目的。然而,當(dāng)我們處理固定掉的數(shù)據(jù)塊(在該實(shí)例中為0×418字節(jié)),很難找到一個(gè)合適大小的對(duì)象導(dǎo)致堆溢出。想要克服該問(wèn)題的人可以參考此處。
溢出內(nèi)核分頁(yè)池
私有命名空間是創(chuàng)建可控大小的分頁(yè)池對(duì)象的有效方法。通過(guò)創(chuàng)建多個(gè)帶有邊界描述符名稱(chēng)的、特制長(zhǎng)度的私有命名空間,我們可以獲得以下內(nèi)存布局:
圖三 堆溢出#1
因此,在這種情況下,我們并不能控制分頁(yè)池?cái)?shù)據(jù)塊的大小,但是,我們可以控制分頁(yè)池對(duì)象的大小,如圖三所示,指定一個(gè)內(nèi)存頁(yè)(4KB)來(lái)顯示分頁(yè)池的開(kāi)始。
也就是說(shuō),我們可以創(chuàng)建一個(gè)控制內(nèi)存頁(yè)開(kāi)始的對(duì)象,然后就可以擁有一個(gè)0x3b8字節(jié)大小的可用空間,和兩個(gè)一直到內(nèi)存頁(yè)結(jié)束都可以控制的相鄰對(duì)象。由于邊界描述符名稱(chēng)的長(zhǎng)度可變,甚至可以使用可控對(duì)象占據(jù)整個(gè)內(nèi)存頁(yè)。
圖四 堆溢出#2
但是,由于可溢出的緩沖區(qū)是固定大?。?×418字節(jié))的,并且可以以?xún)?nèi)存頁(yè)中最后分配的對(duì)象為目標(biāo),因此我們完全不用考慮page_allocation_base + 0×418中的空間內(nèi)容。也就是說(shuō),我們?nèi)匀豢梢栽试S內(nèi)核使用該空間。
通過(guò)使用ProcessExplorer,我們可以更清楚地看到堆溢出后的分頁(yè)池內(nèi)存分配情況,如圖五。
圖五 分頁(yè)池的內(nèi)存分配布局
圖六為堆溢出后的內(nèi)存頁(yè)的布局情況。我們利用該漏洞導(dǎo)致了SnxN緩沖區(qū)的溢出,并損壞了相鄰對(duì)象。
圖六 堆溢出#3
私有命名空間不僅可以使攻擊者控制分頁(yè)池大小,而且可以通過(guò)重寫(xiě)NAMESPACE_DESCRIPTOR結(jié)構(gòu)體的LIST_ENTRY字段中的指針來(lái)控制執(zhí)行情況。該字段將NAMESPACE_DESCRIPTOR結(jié)構(gòu)體鏈接到系統(tǒng)中所有可用私有命名空間的列表。
假定我們已經(jīng)成功損壞了特定私有命名空間的NAMESPACE_DESCRIPTOR結(jié)構(gòu)體的LIST_ENTRY字段。
圖七 不太安全的Unlinking功能(Win 7 SP1)
但是在Windows 8及更高版本中,由于安全的LIST_ENTRY結(jié)構(gòu)體的使用,該方法并不能奏效。
圖八 安全的Unlinking功能(Win 8.1)
圖九為私有命名空間的目錄對(duì)象的損壞前后對(duì)比??梢钥吹?,NAMESPACE_DESCRIPTOR結(jié)構(gòu)體的LIST_ENTRY字段已經(jīng)使用用戶(hù)空間地址(0×41414141)成功重寫(xiě)。
圖九 目錄對(duì)象的損壞前后對(duì)比
控制EIP
成功損壞目錄對(duì)象后,接下來(lái)就是控制漏洞的執(zhí)行了。使用write-what-where條件重寫(xiě)HalDispatchTable的函數(shù)指針,尤其是存儲(chǔ)在HalDispatchTable+sizeof(ULONG_PTR)這的hal!HaliQuerySystemInformation函數(shù),然后通過(guò)調(diào)用ntdll!NtQueryIntervalProfile將漏洞執(zhí)行重定向到我們自己的負(fù)載。
函數(shù)調(diào)用序列為ntdll!NtQueryIntervalProfileà nt!NtQueryIntervalProfile à nt!KeQueryIntervalProfileà call [nt!HalDispatchTable+sizeof(ULONG_PTR)](0×41414141)。
目前我們可以做到的是重寫(xiě)內(nèi)核地址空間中的任意指針,并通過(guò)劫持攻擊控制EIP。但是這是遠(yuǎn)遠(yuǎn)不夠的。
write-what-where條件在斷開(kāi)私有命名空間和系統(tǒng)中可用私有命名空間的連接時(shí)發(fā)生,也就是我們?cè)陉P(guān)閉處理器或者使用特定私有命名空間中的目錄對(duì)象時(shí)。可以通過(guò)調(diào)用ClosePrivateNamespace或CloseHandle來(lái)實(shí)現(xiàn)該過(guò)程。
需要注意的是,為了堆溢出的發(fā)生,分頁(yè)池的數(shù)據(jù)塊頭已經(jīng)損壞,一旦釋放數(shù)據(jù)塊頭中的任意對(duì)象,都會(huì)觸發(fā)SoD,因?yàn)閮?nèi)核會(huì)對(duì)比之前對(duì)象的實(shí)際大小和釋放的數(shù)據(jù)大小。
我們可以通過(guò)隔離這兩個(gè)階段來(lái)避開(kāi)這個(gè)問(wèn)題。我們是通過(guò)調(diào)用ZwDeletePrivateNameSpace而觸發(fā)的what-where條件,這會(huì)導(dǎo)致連接斷開(kāi),但是并不是釋放對(duì)象內(nèi)存。我們可以在post-exploitation清理階段重新保存LIST_ENTRY字段。
最后,我們可以安全地修復(fù)損壞的目錄對(duì)象,和NAMESPACE_DESCRIPTOR結(jié)構(gòu)體,以保證系統(tǒng)不會(huì)報(bào)錯(cuò)。
廠商修復(fù)
圖十 存在漏洞的函數(shù)
圖十一 修復(fù)的函數(shù)
由圖可以發(fā)現(xiàn),修復(fù)的函數(shù)中添加了一個(gè)調(diào)用子程序的call sub_C161C指令,它的目的是驗(yàn)證復(fù)制到固定大小的內(nèi)存中的數(shù)據(jù)大小,如果大小不合適,程序會(huì)調(diào)用ExAllocatePoolWithTag函數(shù)重新分配一個(gè)合適的空間,可以安全地保存數(shù)據(jù)。
*原文地址:nettitude,F(xiàn)B小編vul_wish編譯,轉(zhuǎn)載請(qǐng)注明來(lái)自FreeBuf黑客與極客(FreeBuf.COM)