如何以一種意外的方式發(fā)現(xiàn)并找到 WinIO 內(nèi)核驅(qū)動棧溢出漏洞
研究人員在OEM廠商的外圍設(shè)備中發(fā)現(xiàn)了多個漏洞,這影響了這些OEM廠商(Razer、EVGA、MSI、AMI)的許多用戶。這些漏洞源于一個眾所周知的易受攻擊的驅(qū)動程序,通常被稱為WinIO/WinRing0。
本文會重點介紹一個有趣的TOCTOU漏洞案例(CVE-2022-25637),以及其他一些漏洞。
眾所周知,MSI開發(fā)了一個名為MSI Dragon Center的便捷工具,其目的是檢索有關(guān)計算機統(tǒng)計信息(即GPU/CPU使用情況)并控制硬件相關(guān)設(shè)置。
不過從實際反饋來看,它運行得并不好,出現(xiàn)了許多UI問題并且加載時間慢。有研究人員在調(diào)整MSI電腦上風(fēng)扇的速度時,無疑發(fā)現(xiàn)了其中的問題,很可能是MSI使用了內(nèi)核驅(qū)動程序。本文的作者檢查證實了MSI使用內(nèi)核驅(qū)動程序來執(zhí)行Dragon Center提供的一些功能,即風(fēng)扇控制功能是通過WMI對象或供應(yīng)商特定的API(如NvAPI_GPU_SetCoolerLevels)完成的,并沒有在Dragon Center代碼中實現(xiàn)。此外,Dragon Center加載了一個名為WinIO的驅(qū)動程序,這顯然與風(fēng)扇控制的邏輯無關(guān)。綜合上述事件,我開始研究WinIo驅(qū)動程序,因為它可能會構(gòu)成一個有趣的攻擊面。
WinIO是由www.internals.com開發(fā)的著名內(nèi)核驅(qū)動程序(該網(wǎng)站已不再在線,但可以通過archive.org訪問)。WinIO驅(qū)動程序庫允許32位和64位Windows用戶模式進程直接訪問I/O端口、MSR寄存器和物理內(nèi)存,它已被許多供應(yīng)商廣泛使用。由于它具有強大的功能,因此責(zé)任重大,驅(qū)動程序應(yīng)該只允許特權(quán)用戶使用這些功能。
然而,在WinIo中,情況有所不同,任何用戶都可以與之交互,包括沙盒應(yīng)用程序。WinIo可以簡單地在設(shè)備對象上設(shè)置一個安全描述符,以避免低權(quán)限用戶與其交互,如下面的代碼片段所示。
將SDDL應(yīng)用于設(shè)備對象
我在我的設(shè)備上發(fā)現(xiàn)的WinIo版本是驅(qū)動程序的早期版本(我們懷疑它是WinIo 2.0版),即使是最簡單的漏洞也極易對其發(fā)起攻擊,一個簡單的DeviceIoControl請求可能會破壞堆棧。通過使用具有IOCTL代碼0x80102040的DeviceIoControl發(fā)送I/O請求,研究人員得到了一個memmove方法。
WinIo調(diào)度函數(shù):易受攻擊的memmove/memcpy
此memmove缺少任何參數(shù)檢查。更準(zhǔn)確地說,它屬于控制長度參數(shù),該參數(shù)源自SystemBuffer。因此,通過指定大于IOPM本地變量長度的長度,我們可以很容易地破壞堆棧。因此,我們可以重寫本地堆棧數(shù)據(jù),這是一個經(jīng)典的緩沖區(qū)溢出場景,它可以導(dǎo)致重寫調(diào)用方的返回指針,再加上使用ROP鏈,最終導(dǎo)致權(quán)限升級。
然而,存在另一個漏洞,即通過物理內(nèi)存映射的權(quán)限升級,這允許我們擁有一個強大的R/W原語。
WinIO中的任意內(nèi)存R/W函數(shù)
此時,會出現(xiàn)一個問題,這個代碼庫是否可以用于其他地方\驅(qū)動程序?
尋找其他易受攻擊的程序
我們在VirusTotal中編寫了一個相對簡單的查詢,并找到了114個潛在驅(qū)動程序的匹配項,,這些潛在驅(qū)動程序可能與我們的脆弱驅(qū)動程序共享相同的代碼庫。
通過快速瀏覽一些驅(qū)動程序的逆向代碼,許多供應(yīng)商似乎使用了WinIo驅(qū)動程序的相同易受攻擊的代碼庫。
其中Razer Synapse Service.sys特別引起了我的注意。
Razer Synapse Servicesys VirusTotal結(jié)果
三個異常的Razer Synapse
研究人員的設(shè)備上安裝的是Razer Synapse,Razer Synapse(雷蛇云驅(qū)動)是款云端軟件,配合Razer的鍵鼠使用,可以把游戲配置文件、宏,已經(jīng)鼠標(biāo)等的設(shè)置參數(shù)同步到云端。Razer Synapse加載了一些驅(qū)動程序,其中之一是Razer Synape服務(wù)。sys–具有不同名稱的WinIo驅(qū)動程序。通常,當(dāng)加載WinIo驅(qū)動程序時,不會對設(shè)備對象設(shè)置安全限制。然而,在這種情況下,它有一個限制性的安全描述符。
應(yīng)用于Razer驅(qū)動程序的SDDL
此時,通常應(yīng)該放棄此驅(qū)動程序,即使它是錯誤的,因為為了與此驅(qū)動程序交互,你需要具有高權(quán)限,這意味著你已經(jīng)可以執(zhí)行特權(quán)操作。
在Windows中,如果你以admin+的身份開始,那么讓驅(qū)動程序做一些異常的操作并不會被視為是不安全的事情。由于驅(qū)動程序沒有設(shè)置安全描述符,所以這一定是在其他地方完成的。
根據(jù)MSDN的描述:“設(shè)備對象的安全性可以由放置在INF文件中或傳遞給IoCreateDeviceSecure的SDDL字符串指定?!?/p>
現(xiàn)在,我們應(yīng)該仔細分析一下INF文件,但令人驚訝的是,并沒有INF文件!
不得不說這是一個很奇怪的情況,我們懷疑Razer Synapse Service.exe將SDDL設(shè)置為驅(qū)動程序創(chuàng)建的設(shè)備對象。為此,我們監(jiān)控了Procmon中的系統(tǒng),并注意到該程序負責(zé)加載Razer Synapse Service.sys驅(qū)動程序。
準(zhǔn)備安裝 “Razer Synapse Service.sys”
我們需要對Razer Synapse Service.exe進行逆向工程,以了解它在何處應(yīng)用安全描述符。幸運的是,它是用C#編寫的,這將使我們的逆向工程工作更容易,因為我們可以使用reflector。
通過遍歷模塊列表,找出哪個模塊負責(zé)加載內(nèi)核驅(qū)動程序。我們將不同的模塊反編譯回C#(我們使用了DnSpy),然后繼續(xù)查找與服務(wù)控制管理器(SC管理器)進行的任何通信。我們發(fā)現(xiàn)負責(zé)此事的模塊是LibreHardwareMonitorLib(開源)。
如果我們仔細觀察代碼,就會發(fā)現(xiàn)一些奇怪的東西。
我們可以看到,在第11-14行中,服務(wù)嘗試打開驅(qū)動程序創(chuàng)建的設(shè)備對象的句柄,然后為其設(shè)置新的安全描述符。我的意思是,他們在用戶模式下使用了正確的方法,但他們一開始就不應(yīng)該在用戶模式空間中這樣做。
如上所述,應(yīng)用SDDL應(yīng)該在內(nèi)核中完成,并在設(shè)備創(chuàng)建時完成。事實上,它沒有在內(nèi)核空間中發(fā)生,這導(dǎo)致設(shè)備對象持有一個默認(rèn)的安全描述符,該描述符允許低權(quán)限用戶與設(shè)備對象交互。
這是檢查使用時間漏洞的典型案例。如果我們能夠利用這個短時間段獲取設(shè)備對象的句柄,那么我們就可以濫用WinIo的漏洞。
漏洞利用
“Razer Synapse Service”配置為自動啟動。因此,我們不能從低權(quán)限用戶的角度隨意重新啟動它。要利用該漏洞,就是要在不重新啟動服務(wù)的情況下重新創(chuàng)建競爭條件(race condition)。
事實證明,使用synapse3提供的更新機制,觸發(fā)這種情況相對容易。每當(dāng)安裝新更新或新插件時,Razer Synapse Service將重新啟動。
重新啟動過程包括卸載WinIo驅(qū)動程序,然后重新加載。因此,允許我們觸發(fā)競爭條件。這是通過安裝一個新模塊來完成的,這一操作不需要特權(quán),因為Synsapse3支持Alexa、Chroma Connect、Chroma Studio、Philips HUE等模塊。
模塊列表Synapse 3
如果我們選擇安裝其中一個模塊,synapse3進程將通過命名管道向Razer Central Service發(fā)送命令,以安裝所選模塊。
RazerCentralService.exe啟動模塊安裝,包括停止和啟動RazerSynapse服務(wù),從而卸載和加載驅(qū)動程序。為此,我們創(chuàng)建了一個POC,該POC完成了整個過程,在POC觸發(fā)模塊安裝期間,一個無限的while循環(huán)嘗試使用CreateFile API打開設(shè)備對象的句柄。我們設(shè)法在安全描述符更改之前打開了設(shè)備的句柄,換句話說,我們贏得了競爭。此時,服務(wù)更改安全描述符并不重要,因為我們擁有設(shè)備對象的有效句柄。
現(xiàn)在我們可以自由地與設(shè)備對象交互,可以利用WinIo的一些漏洞。在本文的POC中,我們利用了MSR R/W原語。寫入MSR原語允許我們重寫IA32_LSTAR MSR。這個特定的MSR保存著指向處理系統(tǒng)調(diào)用的內(nèi)核函數(shù)的指針(KiSystemCall64Shadow)。通過重寫函數(shù)指針,我們可以實現(xiàn)任意的內(nèi)核代碼執(zhí)行。
根據(jù)@_xeroxz的經(jīng)驗,我們使用稱為msrexec的工具輕松地開發(fā)了MSR寫入原語漏洞。
總結(jié)
這項研究是我們修設(shè)備風(fēng)扇時無意中發(fā)現(xiàn)的一個漏洞,通過利用一個很酷的競爭條件,導(dǎo)致在內(nèi)核中運行代碼。
本文翻譯自:https://www.cyberark.com/resources/threat-research-blog/inglourious-drivers-a-journey-of-finding-vulnerabilities-in-drivers