可以利用跨進(jìn)程內(nèi)存泄漏的漏洞逃逸Chrome沙箱,在發(fā)起此攻擊之前,仍然需要攻擊者破壞渲染器,為了防止對(duì)受影響的CPU的攻擊,請(qǐng)確保microcode是最新的,并禁用超線程(HT)。
在我的上一個(gè)文章“破壞數(shù)據(jù)流”中,我描述了如何利用Chrome的JavaScript引擎V8中的漏洞來(lái)在渲染器中執(zhí)行代碼。為了使這種利用有用,你通常需要將其與第二個(gè)漏洞相關(guān)聯(lián),因?yàn)镃hrome的沙箱會(huì)限制你對(duì)操作系統(tǒng)的訪問(wèn),并且將跨站點(diǎn)渲染器的站點(diǎn)隔離移動(dòng)到單獨(dú)的進(jìn)程中,以防止你繞過(guò)Web平臺(tái)的限制。
在本文中,我們將研究沙盒,尤其是當(dāng)從受感染的渲染器使用RIDL和類(lèi)似的硬件漏洞時(shí)所產(chǎn)生的影響。Chrome的IPC機(jī)制Mojo基于消息路由的機(jī)密,泄漏這些機(jī)密使我們可以將消息發(fā)送到特權(quán)接口,并執(zhí)行不應(yīng)允許渲染器執(zhí)行的操作。我們將使用它來(lái)讀取任意本地文件,以及在Windows上的沙箱外部執(zhí)行。bat文件。在撰寫(xiě)本文時(shí),Apple和Microsoft都在與Chrome安全團(tuán)隊(duì)合作積極致力于修復(fù)此漏洞,以防止這種攻擊。
0x01 背景知識(shí)
以下是Chrome流程模型的簡(jiǎn)要概述:
渲染器進(jìn)程位于單獨(dú)的沙箱中,并且對(duì)內(nèi)核的訪問(wèn)受到限制,例如,通過(guò)Linux上的seccomp過(guò)濾器或Windows 上的 win32k鎖定。但是,為了使渲染器執(zhí)行任何有用的操作,它需要與其他進(jìn)程進(jìn)行對(duì)話(huà)以執(zhí)行各種操作。例如,要加載圖像,將需要要求網(wǎng)絡(luò)服務(wù)代表其獲取圖像。
Chrome中用于進(jìn)程間通信的默認(rèn)機(jī)制稱(chēng)為Mojo。它在后臺(tái)支持消息/數(shù)據(jù)管道和共享內(nèi)存,但是你通常會(huì)使用C ++,Java或JavaScript中的高級(jí)語(yǔ)言之一綁定。也就是說(shuō),你使用自定義接口定義語(yǔ)言(IDL)的方法創(chuàng)建一個(gè)接口,Mojo用你選擇的語(yǔ)言為你生成存根,而你只是實(shí)現(xiàn)了該功能。這可以檢查出URLLoaderFactory .mojom IDL,C ++實(shí)現(xiàn),并在渲染使用。
Mojo的一項(xiàng)顯著功能是允許你通過(guò)現(xiàn)有通道轉(zhuǎn)發(fā)IPC端點(diǎn)。該代碼在Chrome代碼庫(kù)中得到了廣泛使用,即,每當(dāng)你在。mojom文件中看到接收器或遠(yuǎn)程參數(shù)時(shí)。
Mojo在進(jìn)程之間或更具體地在Mojo的節(jié)點(diǎn)之間使用特定于平臺(tái)的消息管道。兩個(gè)節(jié)點(diǎn)可以直接彼此連接,但是由于Mojo支持消息路由,因此不必連接。網(wǎng)絡(luò)中的一個(gè)節(jié)點(diǎn)稱(chēng)為代理節(jié)點(diǎn),它具有一些其他責(zé)任來(lái)設(shè)置節(jié)點(diǎn)通道并執(zhí)行沙箱限制的某些操作。
IPC端點(diǎn)本身稱(chēng)為端口。在上面的URLLoaderFactory示例中,客戶(hù)端和實(shí)現(xiàn)方都由端口標(biāo)識(shí)。在代碼中,端口如下所示:
class Port : public base::RefCountedThreadSafe {
public:
// […]
// The current State of the Port.
State state;
// The Node and Port address to which events should be routed FROM this Port.
// Note that this is NOT necessarily the address of the Port currently sending
// events TO this Port.
NodeName peer_node_name;
PortName peer_port_name;
// The next available sequence number to use for outgoing user message events
// originating from this port.
uint64_t next_sequence_num_to_send;
// […]
}
上面的peer_node_name 和peer_port_name 都是用于尋址的128位隨機(jī)整數(shù)。如果將消息發(fā)送到端口,它將首先將其轉(zhuǎn)發(fā)到正確的節(jié)點(diǎn),接收節(jié)點(diǎn)將在本地端口映射中查找端口名稱(chēng),并將消息放入正確的消息隊(duì)列。
這意味著如果瀏覽器進(jìn)程中存在信息泄漏漏洞,則可以泄漏端口名稱(chēng),并使用它們將消息注入特權(quán)IPC通道。實(shí)際上,在Mojo核心文檔的安全性部分中對(duì)此進(jìn)行了聲明:
“ […]任何節(jié)點(diǎn)只要知道端口和節(jié)點(diǎn)名稱(chēng),就可以將任何消息發(fā)送到任何其他節(jié)點(diǎn)的任何端口。[…]因此,重要的是不要將端口名稱(chēng)泄漏到不應(yīng)被授予相應(yīng)功能的節(jié)點(diǎn)中?!?/p>
可以很容易地利用泄漏的端口號(hào)的一個(gè)漏洞的一個(gè)很好的例子是crbug.com/779314通過(guò)@NedWilliamson。這是blob實(shí)現(xiàn)中的整數(shù)溢出,它使你可以在瀏覽器進(jìn)程中讀取blob前面的任意數(shù)量的堆內(nèi)存。
該漏洞利用過(guò)程將大致如下所示:
1. 破壞渲染器。
2. 使用Blob漏洞泄漏堆內(nèi)存。
3. 在存儲(chǔ)器中搜索端口(有效狀態(tài)+ 16個(gè)高熵字節(jié))。
4. 使用泄漏的端口將消息注入特權(quán)IPC連接。
接下來(lái),我們需要考慮兩件事。如何用CPU漏洞替換上面的第2步和第3步,以及如何通過(guò)特權(quán)IPC連接獲得什么樣的原語(yǔ)。
0x02 RIDL
為了利用此硬件漏洞,我需要尋找另一個(gè)漏洞,該漏洞使你可以跨進(jìn)程邊界泄漏內(nèi)存。來(lái)自MDS攻擊的 RIDL 似乎是最理想的選擇,因?yàn)樗耆梢员WC:它允許你從受影響的CPU上的各種內(nèi)部緩沖區(qū)泄漏數(shù)據(jù)。有關(guān)其工作原理的詳細(xì)信息,請(qǐng)查看論文或PPT,因?yàn)樗鼈儽任夷芙忉尩囊玫枚唷?/p>
已經(jīng)發(fā)布了 microcode和操作系統(tǒng)更新來(lái)解決MDS攻擊。但是,如果你閱讀了英特爾對(duì)該問(wèn)題的深入](https://software.intel.com/security-software-guidance/insights/deep-dive-intel-analysis-microarchitectural-data-sampling)研究,你會(huì)注意到,緩解措施在切換到特權(quán)較低的執(zhí)行上下文時(shí)清除了受影響的緩沖區(qū)。如果你的CPU支持超線程,你仍然可以從物理內(nèi)核上運(yùn)行的第二個(gè)線程中泄漏數(shù)據(jù)。解決此問(wèn)題的建議是禁用超線程或?qū)崿F(xiàn)組調(diào)度程序。
你可以在網(wǎng)上找到多個(gè)驗(yàn)證了該MDS 漏洞的PoC,他們中的一些具有不同的屬性:
· 它們以加載或存儲(chǔ)目標(biāo)。
· 有些要求從L1緩存中清除key。
· 你可以控制64字節(jié)高速緩存行中的索引從先前的訪問(wèn)中泄漏或泄漏64位的值。
· 速度變化很大,取決于變體和漏洞利用。我看到的最高是針對(duì)Brandon Falk的228kB / s 的MLPDS攻擊。為了進(jìn)行比較,我的機(jī)器上的漏洞利用僅達(dá)到25kB / s。
https://gamozolabs.github.io/metrology/2019/12/30/load-port-monitor.html#an-mlpds-exploit
所有利用變體有一個(gè)共同屬性是,它們?cè)谛孤┑膬?nèi)容上具有概率。盡管RIDL論文描述了一些針對(duì)某些值的同步原語(yǔ),但通常需要觸發(fā)對(duì)key的重復(fù)訪問(wèn)才能將其完全泄漏。
我最終使用不同的MDS變體為Chrome編寫(xiě)了兩個(gè)漏洞利用,一個(gè)針對(duì)Xeon Gold 6154上的Linux構(gòu)建,另一個(gè)針對(duì)Core i7-7600U上的Windows。我將描述這兩種方法,因?yàn)樗鼈冊(cè)趯?shí)踐中最終面臨不同的挑戰(zhàn)。
0x03 MFBDS
微體系結(jié)構(gòu)填充緩沖區(qū)數(shù)據(jù)采樣(MFBDS)
我的第一個(gè)漏洞是使用針對(duì)CPU的行填充緩沖區(qū)的MFBDS。PoC非常簡(jiǎn)單:
xbegin out ; start TSX to catch segfault
mov rax, [0] ; read from page 0 => leaks a value from line fill buffer
; the rest will only execute speculatively
and rax, 0xff ; mask out one byte
shl rax, 0xc ; use as page index
add rax, 0x13370000 ; add address of probe array
prefetchnta [rax] ; access into probe array
xend
out: nop
此后,你將定時(shí)訪問(wèn)探針陣列以查看已緩存了哪個(gè)索引。
你可以在開(kāi)頭更改0 ,以控制泄漏的高速緩存行中的偏移量。另外,你還希望按照本文所述在泄漏值上實(shí)現(xiàn)前綴或后綴過(guò)濾器。請(qǐng)注意,這只會(huì)泄漏不在L1高速緩存中的值,因此你希望有一種方法可以在兩次訪問(wèn)之間從高速緩存中移出key值。
對(duì)于我的第一個(gè)泄漏目標(biāo),我選擇了一個(gè)特權(quán)URLLoaderFactory。如上所述,渲染器使用URLLoaderFactory來(lái)獲取網(wǎng)絡(luò)資源。它將為渲染器強(qiáng)制執(zhí)行同源策略(實(shí)際上是相同站點(diǎn)),以確保不會(huì)破壞Web平臺(tái)的限制。但是,瀏覽器進(jìn)程還將URLLoaderFactories用于不同的目的,并且它們具有其他特權(quán)。除了忽略同源策略外,還允許它們上傳本地文件。因此,如果我們可以泄漏其端口名之一,則可以使用它將/ etc / passwd 上傳到https://evil.website。
下一步將觸發(fā)對(duì)特權(quán)加載程序的端口名的重復(fù)訪問(wèn)。使瀏覽器進(jìn)程發(fā)出網(wǎng)絡(luò)請(qǐng)求可能是一種選擇,但似乎開(kāi)銷(xiāo)太大,我決定針對(duì)節(jié)點(diǎn)中的端口查找。
class COMPONENT_EXPORT(MOJO_CORE_PORTS) Node {
// […]
std::unordered_map ports_;
// […]
}
每個(gè)節(jié)點(diǎn)都有一個(gè)存儲(chǔ)所有本地端口的哈希映射。如果我們將消息發(fā)送到不存在的端口,目標(biāo)節(jié)點(diǎn)將在映射中查找它,發(fā)現(xiàn)它不存在并刪除消息。如果我們的端口名與另一個(gè)端口名位于同一哈希庫(kù)中,它將讀取未知端口的完整哈希值以與之進(jìn)行比較。由于端口名通常與散列存儲(chǔ)在同一高速緩存行中,因此這還將端口名本身加載到高速緩存中。MFBDS允許我們泄漏整個(gè)緩存行,即使未直接訪問(wèn)值也是如此。
該maps在一個(gè)新的Chrome實(shí)例上以大約700的存儲(chǔ)大小,并且主要隨著渲染器數(shù)量的增加而增長(zhǎng)。這使攻擊變得不可行,因?yàn)槲覀儗⒉坏貌粡?qiáng)制使用存儲(chǔ)區(qū)索引和緩存行偏移量。但是,我注意到一個(gè)代碼路徑,該路徑使你可以使用服務(wù)工作者創(chuàng)建大量特權(quán)URLLoaderFactories。如果你創(chuàng)建啟用導(dǎo)航預(yù)加載的服務(wù)工作,則每個(gè)導(dǎo)航都將創(chuàng)建這樣的loader。通過(guò)簡(jiǎn)單地創(chuàng)建多個(gè)iframe并在服務(wù)器端停止請(qǐng)求,你可以同時(shí)使數(shù)千個(gè)加載程序保持活動(dòng)狀態(tài),并使暴力破解變得更加容易。
唯一缺少的是從L1緩存中尋找目標(biāo)值。在實(shí)踐中,簡(jiǎn)單地用32KB數(shù)據(jù)填充我們的消息似乎可以解決問(wèn)題,因?yàn)槲艺J(rèn)為數(shù)據(jù)將被加載到受害者的L1緩存中。
總結(jié)完整的利用:
1. 破壞渲染器。
2. 在$ NUM_CPU-1進(jìn)程中以不同的緩存行偏移量運(yùn)行RIDL漏洞。
3. 安裝具有導(dǎo)航預(yù)加載的服務(wù)。
4. 創(chuàng)建許多iframe并暫停其請(qǐng)求。
5. 使用隨機(jī)端口名稱(chēng)將消息發(fā)送到網(wǎng)絡(luò)進(jìn)程。
6. 如果我們?cè)诖鎯?chǔ)索引上發(fā)生沖突,則2.中的過(guò)程可能會(huì)泄漏端口名稱(chēng)。
7. 將消息欺騙到URLLoaderFactory以將本地文件上傳到https://evil.website。
0x04 TSX異步中止(TAA)
在2019年11月發(fā)布了MDS攻擊的新變種,并且由于TAA PoC似乎比我的MFBDS攻擊更快,因此我決定將其改編為Chrome攻擊。此外,VUSec發(fā)布了一項(xiàng)針對(duì)存儲(chǔ)操作的漏洞利用程序,如果我們可以將key寫(xiě)入到內(nèi)存中的不同地址,則該漏洞應(yīng)允許我們逃脫緩存刷新要求。如果我們可以觸發(fā)瀏覽器將消息發(fā)送到特權(quán)端口,則應(yīng)該發(fā)生這種情況。在這種情況下,secret端口名稱(chēng)也將以節(jié)點(diǎn)名稱(chēng)作為前綴,并且我們可以使用RIDL文件中的技術(shù)輕松對(duì)其進(jìn)行過(guò)濾。
我還開(kāi)始尋找一個(gè)更好的原語(yǔ),發(fā)現(xiàn)如果可以與NetworkService進(jìn)行通信,它將允許我創(chuàng)建一個(gè)新的NetworkContext,從而選擇存儲(chǔ)cookie的sqlite3數(shù)據(jù)庫(kù)的文件路徑。
為了找出如何觸發(fā)從瀏覽器進(jìn)程到NetworkService的消息,我查看了界面中的IPC方法,以找到一種看起來(lái)可以從渲染器影響它的方法。NetworkService.OnPeerToPeerConnectionsCountChange引起了我的注意,實(shí)際上,每次更新WebRTC連接時(shí)都會(huì)調(diào)用此方法。你只需要?jiǎng)?chuàng)建一個(gè)偽造的WebRTC連接,每次將其標(biāo)記為已連接/斷開(kāi)連接時(shí),都會(huì)觸發(fā)一條新消息給NetworkService。
一旦從受破壞的渲染器中泄漏了端口名稱(chēng),我們就獲得了編寫(xiě)具有完全受控路徑的sqlite3數(shù)據(jù)庫(kù)的原語(yǔ)。
雖然起初聽(tīng)起來(lái)并不是很有用,但是你實(shí)際上可以濫用它來(lái)獲得代碼執(zhí)行。我注意到Windows批處理文件是一種非常好的文件格式。如果文件的開(kāi)頭有g(shù)adget,它將跳過(guò)它直到下一個(gè)“ \ r \ n”并從那里執(zhí)行下一個(gè)命令。在我的漏洞利用中,我使用它在用戶(hù)的自動(dòng)運(yùn)行目錄中創(chuàng)建一個(gè)cookies.bat文件,添加帶有“ \ r \ n”的cookie和其中的命令,它將在下次登錄時(shí)執(zhí)行。
最終,此漏洞利用平均在我的機(jī)器上執(zhí)行了1-2分鐘,并且持續(xù)不到5分鐘。而且我敢肯定,由于某些技術(shù)可以大大提高速度,因此可以大大改善這一點(diǎn)。例如,實(shí)際上MLPDS似乎比我使用的變體更快。
利用步驟:
1. 破壞渲染器。
2. 在$ NUM_CPU-1進(jìn)程中以不同的緩存行偏移量運(yùn)行RIDL漏洞。
3. 創(chuàng)建偽造的WebRTC連接,并在已連接和已斷開(kāi)連接之間切換。
4. 泄漏NetworkService端口名稱(chēng)。
5. 使用c:\ path \ to \ user \ autorun \ cookies.bat中的cookie文件創(chuàng)建一個(gè)新的NetworkContext
6. 插入cookie“ \ r \ ncalc.exe \ r \ n”。
7. 等待下一次登錄。
0x05 分析總結(jié)
當(dāng)我開(kāi)始研究此問(wèn)題時(shí),我感到驚訝的是,即使漏洞已經(jīng)公開(kāi)了一段時(shí)間,它仍然可以被利用。如果你閱讀有關(guān)該主題的指南,則他們通常會(huì)在你的操作系統(tǒng)為最新的情況下談?wù)撊绾尉徑膺@些漏洞,并應(yīng)注意你應(yīng)禁用超線程以完全保護(hù)自己。專(zhuān)注于緩解措施無(wú)疑給我一種感覺(jué),那就是漏洞已得到解決,我認(rèn)為這些文章對(duì)于啟用超線程的影響可能會(huì)更加清楚。
話(huà)雖如此,我希望你從這篇文章中思考兩個(gè)問(wèn)題。首先,信息泄漏漏洞不僅僅可以繞過(guò)ASLR。即使不是依靠key端口名,也可能會(huì)泄漏其他有趣的數(shù)據(jù),例如Chrome的UnguessableTokens,Gmail cookie或計(jì)算機(jī)其他進(jìn)程中的敏感數(shù)據(jù)。如果你對(duì)如何大規(guī)模查找信息泄漏有所了解,Chrome可能是一個(gè)不錯(cuò)的選擇。
其次,由于硬件漏洞超出了我的研究范圍,因此我長(zhǎng)時(shí)間忽略了它們。但是,我希望我可以通過(guò)此文章為你提供有關(guān)其影響的另一個(gè)數(shù)據(jù)點(diǎn),以幫助你做出是否應(yīng)該禁用超線程的決定。對(duì)于可以用類(lèi)似的方式破壞其他軟件的方式,還有很多探索的余地,我很樂(lè)意看到更多應(yīng)用硬件漏洞突破軟件安全性邊界的示例。