由于Firefox母公司的隱私保護措施,F(xiàn)irefox 有時會被默認為一種更安全的瀏覽器。本文將詳細反駁,并對標 Chromium,研究 Firefox 瀏覽器在進程沙箱模型、漏洞利用緩解技術等方面的不足。
沙箱
沙箱是一種用于隔離某些程序的技術,以防止它們中的漏洞通過限制對不必要資源的訪問而危及系統(tǒng)的其他部分?,F(xiàn)在所有常見的瀏覽器都包含一個沙箱并利用多進程架構。瀏覽器將自己分成不同的進程(例如內容進程、GPU 進程、RDD 進程等)并將它們分別沙箱化,嚴格遵守最小權限原則。瀏覽器使用沙箱非常重要,因為它會處理不受信任的輸入,帶來巨大的攻擊面,并且是系統(tǒng)上最常用的應用程序之一。如果沒有沙箱,瀏覽器中的任何漏洞都可以用來接管系統(tǒng)的其余部分。而對于沙箱,攻擊者需要將他們的利用與額外的沙箱逃逸漏洞聯(lián)系起來。
如果沙箱充滿漏洞,那么僅僅有一個沙盒是沒有多大作用的。Firefox 的沙箱非常脆弱,下面的漏洞只是幾個示例。
網(wǎng)站隔離
網(wǎng)站隔離是 2018 年 Chromium 中引入的一項安全功能,這涉及對 Chromium 多進程架構的徹底改革,而不是所有的網(wǎng)站都運行在同一個進程中,該功能現(xiàn)在將每個網(wǎng)站劃分到自己的沙箱渲染器進程中。這確保了來自一個網(wǎng)站的渲染器漏洞仍然無法訪問來自另一個網(wǎng)站的數(shù)據(jù)。此外,網(wǎng)站隔離對于完全防止諸如 Spectre 之類的側信道攻擊是必要的。針對此類攻擊的操作系統(tǒng)緩解措施僅保證進程邊界的隔離。因此,將網(wǎng)站分成不同的進程是充分利用它們的唯一途徑。此外,當前的瀏覽器緩解措施(例如降低 JavaScript 計時器的準確性)是不夠的,無法解決根本問題。因此,唯一適當?shù)木徑獯胧┦峭ㄟ^網(wǎng)站隔離。
Firefox 目前缺乏任何形式的網(wǎng)站隔離,Mozilla 正在通過 Project Fission 實現(xiàn)這一功能,并在 Nightly 和 Beta 發(fā)布渠道上推出,但它仍在進行中,還不適合正式使用。Fission 在目前的狀態(tài)下,即使它最初發(fā)布,也不會接近 Chromium 網(wǎng)站隔離的成熟水平,它需要很多年才能達到這一點。Fission 仍然存在基線內容流程沙箱的所有安全問題,如下所述——它不是解決所有沙箱問題的靈丹妙藥。然而,具體到 Fission 本身,存在大量跨網(wǎng)站泄漏,允許受攻擊的內容進程訪問另一個的數(shù)據(jù)并繞過網(wǎng)站隔離。
Windows
排除網(wǎng)站隔離的問題,只有 Windows 上的 Firefox 沙箱可以與 Chromium 沙箱相媲美,但它仍然缺乏 Win32k Lockdown。Win32k 是 NT 內核中一組危險的系統(tǒng)調用,它暴露了大量的攻擊面,使其成為沙箱逃逸的常見目標。Microsoft 旨在通過引入一項功能來降低這種風險,該功能允許進程阻止對這些系統(tǒng)調用的訪問,從而大大減少攻擊面。Chromium 在 2016 年實現(xiàn)了此功能以加強沙箱檢測,但 Firefox 尚未添加此功能。
Linux
?沙箱逃逸
Firefox 在其他平臺(如 Linux)上的沙箱效果要差得多,這些限制通常非常寬松,甚至容易受到跨越多年的各種瑣碎的沙箱逃逸漏洞的影響,以及從沙箱內部暴露出相當大的攻擊面。
此類沙箱逃逸漏洞的一個示例是 X11 — X11 沒有實現(xiàn)任何 GUI 隔離,這使得使用它逃逸沙箱變得非常容易。Chromium 通過只允許從 GPU 進程內部訪問 X11 來解決這個問題,因此渲染器進程(加載網(wǎng)站的進程)無法訪問它,而在 Firefox 上,它直接暴露給內容進程。
PulseAudio是Linux上的一個常見的聲音服務器,但是,在編寫時并沒有考慮到隔離,這使得使用它可以脫離沙箱。像X11一樣,F(xiàn)irefox直接將其暴露給內容進程,允許另一個微不足道的沙箱逃脫,而Chromium只將其暴露給一個專門的音頻服務。
?seccomp-bpf
seccomp-bpf 是 Linux 上的一種沙箱技術,它允許限制進程可訪問的系統(tǒng)調用,這可以大大減少內核攻擊面,并且是大多數(shù) Linux 沙箱的核心部分。但是,F(xiàn)irefox 的 seccomp 過濾器比 Chromium 的沙箱強加的過濾器的限制要少得多,而且它對系統(tǒng)調用及其參數(shù)的限制也不相同。這方面的一個示例是對ioctl調用幾乎沒有過濾,只有與 TTY 相關的 ioctl 在內容過程中被阻止。這是有問題的,因為因為ioctl是一個特別強大的系統(tǒng)調用,它由數(shù)百個不同的系統(tǒng)調用組成,有點類似于NT的Win32k,因此會造成大量的內核攻擊。與Firefox不同,Chromium只允許其沙箱中必需的少數(shù) ioctl,這可顯著減少內核攻擊面。出于同樣的原因,Android 以類似的方式在其應用程序沙箱中實現(xiàn)了 ioctl 過濾,以及其他各種專注于沙箱的項目。
安卓
在Android上,F(xiàn)irefox除了操作系統(tǒng)應用程序的沙箱之外,根本沒有多進程架構或沙箱,而Chromium使用了isolatedProcess特性,以及更嚴格的seccomp-bpf過濾器。
缺少的進程
總的來說,Chromium的多進程體系結構比Firefox的更加成熟和細粒度,允許它對瀏覽器的每個部分施加更嚴格的限制。下面列出了Firefox中缺少的進程示例。在Firefox上,這些功能將被合并到另一個進程中,比如父進程或內容進程,這使得執(zhí)行嚴格的限制變得相當困難。
在 Linux 上,F(xiàn)irefox 沒有單獨的 GPU 進程,這意味著它不能被獨立沙箱化。這個進程在Windows上存在,但是它的沙箱仍然沒有啟用。
Firefox 還沒有單獨的用于網(wǎng)絡操作的 socket 進程,這個進程只存在于 Nightly 中,不包括 WebRTC 代碼以外的任何東西,這與 Chromium 的專用網(wǎng)絡服務不同。
Firefox 也沒有音頻進程,而 Chromium 有專門的音頻服務。Firefox 中缺少這樣的進程意味著音頻功能被合并到內容進程中,這就是 Linux 系統(tǒng)上 PulseAudio 沙箱逃逸向量的原因。
其他示例包括文本轉語音、打印后端和合成器、語音識別、代理解析器等。
緩解措施方面
Firefox缺乏許多重要的緩解措施,而Chromium通常在這方面更勝一籌。
任意代碼保護和代碼完整性保護
一種非常常見的利用技術是,在利用緩沖區(qū)溢出漏洞期間,攻擊者將他們自己的惡意代碼(稱為shellcode)注入到內存的一部分,并通過重寫關鍵數(shù)據(jù)(如返回地址和函數(shù)指針),使程序執(zhí)行它,劫持控制流并指向前面提到的shellcode,從而獲得對程序的控制。
該行業(yè)最終演變?yōu)橥ㄟ^將內存的可寫區(qū)域標記為不可執(zhí)行和可執(zhí)行區(qū)域為不可寫來緩解這種類型的攻擊,從而防止攻擊者注入和執(zhí)行其 shellcode。但是,攻擊者可以通過重用程序(稱為gadget)中已經(jīng)存在的代碼位來繞過它們,這超出了它們最初打算使用的順序。盡管有上述保護措施,攻擊者仍可以利用諸如返回導向編程 (ROP) 或跳轉導向編程 (JOP) 等技術形成一系列此類gadget,以實現(xiàn)近乎任意的代碼執(zhí)行。
攻擊者經(jīng)常將他們的 shellcode 注入可寫內存頁面,然后使用這些代碼重用技術將內存頁面轉換為可執(zhí)行(使用系統(tǒng)調用,例如 mprotect 或 VirtualAlloc),從而允許它被執(zhí)行。Windows 10實現(xiàn)了一個稱為任意代碼保護(ACG)的緩解措施,它通過確保所有可執(zhí)行內存頁面都是不可變的并且永遠無法寫入來緩解這種情況。
另一種稱為代碼完整性保護 (CIG) 的緩解措施類似于 ACG,但它適用于文件系統(tǒng)而不是內存,通過保證加載到進程中的所有二進制文件都必須簽名來確保攻擊者無法在磁盤上執(zhí)行惡意程序或庫。 ACG 和 CIG 一起在內存和文件系統(tǒng)中執(zhí)行嚴格的 W^X 策略。
2017 年,Chromium 實現(xiàn)了對 ACG 和 CIG 的支持,如 MITIGATION_DYNAMIC_CODE_DISABLE 和 MITIGATION_FORCE_MS_SIGNED_BINS,但 Firefox 尚未實現(xiàn)對 ACG 或 CIG 的類似支持。目前Firefox只在socket進程中啟用ACG和CIG(目前還沒有啟用)和在RDD進程中啟用CIG。
然而,由于與JIT引擎的內在不兼容,Chromium的ACG應用目前仍然受到限制,因為JIT引擎需要同時具有可寫和可執(zhí)行的內存。ACG主要是在相對次要的進程中啟用的,例如音頻、代理解析器和圖標讀取器進程。如果V8啟用了JITless模式,那么Chromium在渲染過程中也啟用了ACG。
Chromium 在無 JITless 模式下運行時在渲染器進程中啟用 ACG
如果啟用了 NetworkServiceCodeIntegrity 功能,Chromium 可以選擇在網(wǎng)絡進程中啟用 CIG
控制流的完整性
如前所述,代碼重用攻擊可用于通過將程序中已經(jīng)存在的代碼片段鏈接在一起來實現(xiàn)近乎任意的代碼執(zhí)行,ACG 和 CIG 僅緩解了一種潛在的攻擊向量,創(chuàng)建 ROP/JOP 鏈以將映射轉換為可執(zhí)行文件。但是,攻擊者仍然可以使用純 ROP/JOP 鏈,完全依賴預先存在的gadget,而無需引入自己的代碼。這可以通過控制流完整性 (CFI) 來緩解,CFI 嚴格限制攻擊者能夠使用的gadget,從而破壞他們的鏈。
CFI通常有兩部分:前邊緣保護(覆蓋JOP、COP等)和后邊緣保護(覆蓋ROP)。CFI實現(xiàn)可以有很大的不同。有些CFI實現(xiàn)只覆蓋前邊緣或后邊緣。有些是粗粒度的(攻擊者有更多的通道來執(zhí)行大量的指令)而不是細粒度的。有些是概率性的(它們依賴于所持有的秘密并且不保證安全屬性)而不是確定性的。
Mozilla 計劃實施 CFI 已有一段時間,但尚未取得太大進展。在 Linux、Android 和 ChromeOS 上,Chromium 啟用 Clang 的細粒度前沿 CFI,而在 Windows 上,它啟用粗粒度前沿控制流保護 (CFG)。Firefox 只在 Windows 上啟用 CFG,它不如 Clang 的 CFI 有效,因為它是粗粒度的而不是細粒度的,并且不適用于其他平臺。
不受信任的字體攔截
不受信任的字體歷來是Windows漏洞的常見來源,因此,Windows包括一個緩解措施,以阻止來自特定進程的不受信任的字體,以減少攻擊面。2016年,Chromium以MITIGATION_NONSYSTEM_FONT_DISABLE的形式添加了對這一功能的支持,并為大多數(shù)子進程啟用了這一功能,但是Firefox還沒有在任何子進程中啟用這一功能。
JIT 強化技術
所有常見的瀏覽器都包含一個JIT編譯器以提高性能,然而,JIT中存在一個固有的安全漏洞,那就是對可寫和可執(zhí)行內存的要求,這是一個W^X沖突,如上所述,可以幫助利用它。為了在不犧牲性能提升的情況下降低此功能帶來的安全風險,瀏覽器采用了 JIT 強化技術,使利用 JIT 編譯器變得更加困難。在 Chris Rohlf關于攻擊 JIT 編譯器的研究中,分析和比較了在各種 JIT 引擎中實現(xiàn)的強化技術。這項研究表明,Chromium (V8) 中的 JIT 引擎比 Firefox (JaegerMonkey) 中使用的引擎具有更好的保護。特別是,Chromium 使用但 Firefox 沒有使用的緩解措施包括:
?保護頁面;
?頁面隨機化;
?Constant blinding;
?分配限制;
?NOP 插入;
?隨機代碼庫偏移量;
改進措施
Firefox 試圖通過添加所謂的“W^X JIT”來強化 JIT 引擎,但這并不能阻止實際的漏洞利用,因為它容易受到競爭窗口的影響,在該窗口中,攻擊者可以在可寫時將其 shellcode 寫入內存映射并等待引擎將其轉換為可執(zhí)行文件。此外,由于 Firefox 中缺少 CFI,攻擊者也可以使用許多gadget來強制將映射轉換為可執(zhí)行文件,例如 C 庫中的 ExecutableAllocator::makeExecutable 或 mprotect / VirtualAlloc。類似于 Safari 的“Bulletproof JIT”的東西會是一個更好的方法,它利用兩個獨立的映射,一個可寫的和一個可執(zhí)行的,可寫映射被放置在內存中的一個秘密位置,通過只執(zhí)行內存隱藏。
經(jīng)過分析,這不是一個很成熟的安全措施。
內存分配器強化
此外,F(xiàn)irefox 缺乏強化的內存分配器。Firefox 目前使用 mozjemalloc,它是 jemalloc 的一個分支。Jemalloc 是一個面向性能的內存分配器,但它不關注安全性,這使得它很容易被利用。Mozjemalloc 確實為 jemalloc 添加了一些有用的安全功能,但它們不足以解決分配器整體架構中存在的問題。Chromium 改為使用 PartitionAlloc(由于 PartitionAlloc-Everywhere 在整個代碼庫中),它比 mozjemalloc 更加堅固。
與mozjemalloc相比,在PartitionAlloc中有一些在mozjemalloc中不存在的安全特性。
?內存分區(qū)
內存分區(qū)是一種漏洞利用緩解措施,其中內存分配器將不同類型的對象隔離到它們自己獨立的堆中。
Chromium 的 PartitionAlloc 在設計時就考慮到了這種緩解措施,分區(qū)之間不重用內存的強內存分區(qū)是PartitionAlloc的核心目標之一。
Firefox的mozjemalloc最終也實現(xiàn)了對分區(qū)的一些支持,但是,內存是跨分區(qū)重用的,因此嚴重削弱了這個特性,并允許它被繞過。因此,mozjemalloc的內存分區(qū)實現(xiàn)并不能保證像PartitionAlloc那樣的強隔離。
?脫機元數(shù)據(jù)
傳統(tǒng)的堆利用技術通常依賴于破壞內存分配器元數(shù)據(jù)。PartitionAlloc 將大多數(shù)元數(shù)據(jù)離線存儲在專用區(qū)域中(除了空閑列表指針,它們還有其他保護)而不是將其與分配相鄰,從而顯著增加了執(zhí)行此類技術的難度。
與PartitionAlloc不同的是,mozjemalloc目前將堆元數(shù)據(jù)放在與分配一致的位置。因此,上述技術仍然是可能的,分配器元數(shù)據(jù)更容易被攻擊。