作者:騰訊研發安全團隊 Martinzhou;騰訊藍軍 Neargle、Pass
原文鏈接:https://mp.weixin.qq.com/s/f0aFLEKyABpYDobPN2b6tQ
I. 背景
數月前我們在攻防兩個方向經歷了一場 “真槍實彈” 的考驗,期間團隊的目光曾一度聚焦到 Chromium 組件上。
其實,早在 Microsoft 2018 年宣布 Windows 的新瀏覽器 Microsoft Edge 將基于 Chromium 內核進行構建之前,伴隨互聯網發展至今的瀏覽器之爭其實早就已經有了定論,Chromium 已然成為現代瀏覽器的事實標準,市場占有率也一騎絕塵。在服務端、桌面還是移動端,甚至據傳 SpaceX 火箭亦搭載了基于 Chromium 開發的控制面板。

Chromium內核的安全問題,早已悄無聲息地牽動著互聯網生活方方面面。基于對實戰經歷的復盤,本文將從Chromium架構及安全機制概況入手,剖析Chromium組件在多場景下給企業帶來的安全風險并一探收斂方案。
II. 淺析Chromium
2.1 Chromium涉及哪些組件?
Chromium主要包含兩大核心組成部分:渲染引擎和瀏覽器內核。
2.1.1 渲染引擎
Chromium目前使用Blink作為渲染引擎,它是基于webkit定制而來的,核心邏輯位于項目倉庫的third_party/blink/目錄下。渲染引擎做的事情主要有:
1) 解析并構建DOM樹。Blink引擎會把DOM樹轉化成C++表示的結構,以供V8操作。
2) 調用V8引擎處理JavaScript和Web Assembly代碼,并對HTML文檔做特定操作。
3) 處理HTML文檔定義的CSS樣式
4) 調用Chrome Compositor,將HTML對應的元素繪制出來。這個階段會調用OpenGL,未來還會支持Vulkan。在Windows平臺上,該階段還會調用DirectX庫處理;在處理過程中,OpenGL還會調用到Skia,DirectX還會調用到ANGLE。
Blink組件間的調用先后關系,可用下圖概括:

可以說,幾乎所有發生在瀏覽器頁簽中的工作,都有Blink參與處理。由于涉及許多組件庫,不難想象過程中可能會出現的安全風險一定不少。據《The Security Architecture of the Chromium Browser》一文的統計數據,約67.4%的瀏覽器漏洞都出在渲染引擎中,這也是為什么要引入Sandbox這么重要。
2.1.2 瀏覽器內核
瀏覽器內核扮演連接渲染引擎及系統的“中間人”角色,具有一定“特權”,負責處理的事務包括但不限于:
1) 管理收藏夾、cookies以及保存的密碼等重要用戶信息
2) 負責處理網絡通訊相關的事務
3) 在渲染引擎和系統間起中間人的角色。渲染引擎通過Mojo與瀏覽器內核交互,包含組件:download、payments等等。
2.2 Chromium 的沙箱保護原理 / 機制
2.2.1 為什么要引入沙箱?
前述部分提到,Chromium 渲染引擎涉及大量 C++ 編寫的組件,出現漏洞的概率不小。因此,基于縱深防御理念瀏覽器引入了涉及三層結構。
渲染引擎等組件不直接與系統交互,而是通過一個被稱為 MOJO 的 IPC 組件與瀏覽器引擎通訊(也被稱為:broker),再與系統交互。進而可以實現:即便沙箱中的進程被攻破,但無法隨意調用系統 API 產生更大的危害。
有點類似:即便攻破了一個容器實例,在沒有逃逸或提權漏洞的情況下,宿主機安全一定程度上不受影響(實際上,瀏覽器的 Sandbox 和容器隔離的部分技術原理是相似的)。

2.2.2 瀏覽器的哪些部分是運行在沙箱中的?
瀏覽器渲染引擎、GPU、PPAPI 插件以及語音識別服務等進程是運行在沙箱中的。此外不同系統平臺下的部分服務也會受沙箱保護,例如 Windows 下打印時調用的 PDF 轉換服務、icon 瀏覽服務;MacOS 下 NaCl loader、需要訪問 IOSurface 的鏡像服務等。
更多細節可查閱 Chromium 項目文件 sandbox_type.h 和 sandbox_type.cc 中的源碼定義:

2.2.3 Windows和Linux下沙箱實現的技術細節
1) Windows
在Windows平臺上,Chrome組合使用了系統提供的Restricted Token、Integrity Level、The Windows job object、The Windows desktop object機制來實現沙盒。其中最重要的一點是,把寫操作權限限制起來,這樣攻擊這就無法通過寫入文件或注冊表鍵來攻擊系統。
2) Linux
Chrome 在 Linux 系統上使用的沙箱技術主要涉及兩層:
第一層沙箱采用 setuid sandbox 方案。
其主要功能封裝在二進制文件 chrome_sandbox 內,在編譯項目時需要單獨添加參數 “ninja -C xxx chrome chrome_sandbox” 編譯,可以通過設置環境變量 CHROME_DEVEL_SANDBOX 指定 Chrome 調用的 setuid sandbox 二進制文件。
setuid sandbox 主要依賴兩項機制來構建沙盒環境:CLONE_NEWPID 和 CLONE_NEWNET 方法。
CLONE_NEWPID 一方面會借助 chroots,來限制相關進程對文件系統命名空間的訪問;另一方面會在調用 clone() 時指定 CLONE_NEWPID 選項,借助 PID namespace,讓運行在沙盒中的進程無法調用 ptrace() 或 kill() 操作沙盒外的進程。
而 CLONE_NEWNET 則用于限制在沙盒內進程的網絡請求訪問,值得一提的是,使用該方法需要 CAP_SYS_ADMIN 權限。
這也使得當 Chrome 組件在容器內運行時,沙箱能力所需的權限會和容器所管理的權限有沖突;我們無法用最小的權限在容器里啟動 Chrome 沙箱,本文 4.2.2 部分會詳細闡述此處的解決之道。

- 更多詳參見 Linux Namespace 及 cgroups 介紹說明:
"Resource management: Linux kernel Namespaces and cgroups"
-https://sites.cs.ucsb.edu/~rich/class/cs293b-cloud/papers/lxc-namespace.pdf
由于 setuid sandbox 方案存在一定短板。自 Chrome 44 版本起已推薦 namespaces sandbox 來替代 setuid sandbox 方案,其主要依賴于 Linux 內核提供的 user namespaces 機制,相關邏輯可在項目的如下行代碼看到:

第二層沙箱采用 Seccomp-BPF 方案,用來限制進程訪問內核特定攻擊面。
其原理是:通過將 Seccomp 和 BPF 規則結合,實現基于用戶配置的策略白名單,對系統調用及其參數進行過濾限制。

2.3 小結
Chromium 涉及的組件眾多,使用的 C++ 語言天然決定了會潛在不少安全問題。例如:一個 V8 中的內存安全問題(如:CVE-2021-21220、CVE-2019–5782),組合 Web Assembly 將 Shellcode 寫入 RWX Pages,在未受沙箱保護的情況下,就能實現遠程代碼執行。
沙箱機制組合使用了 OS 相關的隔離能力(如:Linux 平臺上的 namespace、Seccomp-BPF 機制),限制了被沙箱保護進程的資源訪問以及 syscall 能力,能很好的防止出現在渲染引擎中的漏洞,被用于直接實現 RCE :但沙箱機制也存在一些不足,歷史上也出現過沙箱逃逸的漏洞,例如:Google Project Zero 團隊曾發布的《Virtually Unlimited Memory: Escaping the Chrome Sandbox》一文。
綜上,在無法 100% 預防 Chromium 渲染進程出現內存安全問題的情況下,開啟沙箱保護是一項必須落地的最佳安全實踐。
III. Chromium 漏洞攻擊利用場景分析
作為一款客戶端組件,在評估 Chromium 漏洞時,常常會聚焦于客戶端的攻防場景。但根據我們的經驗,受 chromium 漏洞影響的不僅有客戶端應用,也包含了服務器上運行的程序,例如:部署在服務器端、基于 Chrome Headless 應用的爬蟲程序等。
3.1 服務器端
3.1.1 禁用沙盒的 chromium headless 應用
隨著 Phantomjs 項目停止維護,Chromium headless 已經成為 Headless Browser 的首選。在日常開發、測試、安全掃描、運維中,有許多地方會用到 Headless Browser,包括不限于以下場景:
-
前端測試
-
監控
-
網站截圖
-
安全掃描器
-
爬蟲
在這些場景中,如果程序本身使用的 Chromium 存在漏洞,且訪問的 URL 可被外部控制,那么就可能受到攻擊最終導致服務器被外部攻擊者控制。
以常見的使用 Chrome headless 的爬蟲為例,如果在一些網站測試投放包含 exploit 的鏈接,有概率會被爬蟲獲取,相關爬取邏輯的通常做法是新建 tab 導航至爬取到的鏈接。此時,如果爬蟲依賴的 chromium 應用程序更新不及時,且啟動時設置了 --no-sandbox 參數,鏈接指向頁面內的 exploit 會成功執行,進而允許攻擊者控制爬蟲對應的服務器。
為何 --no-sandbox 會如此泛濫呢?我們不妨來看一下,當我們在 ROOT 下啟動 Chrome,會有什么樣的提示呢?

我們會得到 Running as root without --no-sandbox is not supported 的錯誤提示,且無法啟動 Chrome;
這對于以研發效率和產品功能優先的研發同學來說無異于提示 “請使用? --no-sandbox 來啟動 Chrome”, 應用容器化的進程也加劇了使用 ROOT 用戶啟動應用程序的情況。
你不得不創建一個新的普通用戶來啟動 Chrome 服務,例如在 Dockerfile 里加入 RUN__useradd chrome 和 USER chrome 語句;
有些基于 Chrome 的著名第三方庫甚至會在代碼中隱形植入關閉 sandbox 的代碼,當研發同學在 ROOT 下啟動應用程序時,第三方庫會默認關閉 sandbox,添加 --no-sandbox 參數,例如 Golang 第三方 package Chromedp 的代碼:

此時,對于開發同學來說使用 --no-sandbox 參數甚至是無感的,直至自己的容器或服務器被攻擊者入侵控制。
即使研發同學有啟用 sandbox 來避免安全風險的意識,在容器化的應用內啟動 chrome 也是不易的;為鏡像創建一個新的非 ROOT 用戶并非唯一的條件,Chrome sandbox 需要調用一些特定的 syscall 或 linux capabilities 權限用于啟動 sandbox 邏輯,同時容器鏡像需要打入 chrome-sandbox 二進制文件并寫入環境變量以供 Chrome 進程找到 sandbox 程序。若未對 Chrome 容器進行特定的權限配置,chrome 將輸出 Operation not permitted 報錯信息并退出。
所以,網絡上有大量的文檔和博客推薦啟用 --no-sandbox 來解決 Chrome headless 的使用問題,這也間接助長了 --no-sandbox 參數這種錯誤用法的泛濫:

我們將在后面的章節里詳細為您講解 Chrome Sandbox 在容器以及容器集群中方便快捷且安全合理的部署解決方案。
3.1.2 淺議攻擊方式
未知攻焉知防?雖然在已有 Exploit 的情況下進行漏洞利用并不困難,但知悉漏洞利用的流程和攻擊行為有助于我們更好的構建安全能力。
以下以最近的 CVE-2021-21224 漏洞為例,當服務端上程序使用的 chromium 版本存在漏洞時,且未開啟 Sandbox,可以利用這個漏洞來獲取服務器的權限。
首先攻擊者使用 metasploit 生成 shellcode,這里假設 chromium 是在 linux 上運行且架構為 x64。同時,考慮到爬蟲運行結束后往往會結束瀏覽器進程,通過設置 PrependFork 為 true 可以保證 session 的持久運行。

生成 shellcode 后監聽端口:

實戰中,可以通過投遞帶 exploit 的鏈接到各個網站上,這里假設攻擊者控制的服務器正在被爬取或者正在被滲透測試人員的掃描器掃描:

成功獲取到爬蟲 / 掃描器的服務器 session:

meterpreter 的進程是 fork 后的 chrome 子進程:

可以猜想,不僅是各種內嵌瀏覽器的客戶端程序易受chromium相關漏洞影響,可能有相當多的服務端程序也暴露在chromium 0Day/Nday的攻擊下。chromium漏洞將會成為企業防御邊界的新的突破口,而這個突破口是自內而外的,相比開放端口在外的服務漏洞,這種攻擊可能會更隱蔽。
作為防御方,我們也可以利用chromium漏洞來反制一些攻擊者,如果攻擊者安全意識較差或者使用的工具安全性不強,防御方在服務器上托管帶有exploit的網頁,攻擊者的爬蟲/掃描器掃到了這些網頁就可能被反制攻擊。
3.2 客戶端
在面對Chromium組件風險時,客戶端場景往往首當其沖。通常,其風險成立條件有兩點:1. 使用了存在漏洞的Chromium組件;2. 可以指定Webview組件訪問特定的網站地址。
3.2.1 移動客戶端
目前,移動客戶端主要分兩大“陣營”:安卓和iOS,最大相關風險是Webview類組件。前者 Android System Webview是基于Chromium源代碼開發的,所以當1 Day披露時,需要及時跟進影響;iOS App一般會使用WKWebView和JavaScriptCore,Chromium 1 Day影響iOS應用的可能性較低。
1)客戶端內置 Webview 瀏覽器窗口
除了使用系統自帶的 Webview 組件,另外一種比較常見且更容易引起注意的方式是使用應用內置或獨立于系統之外的瀏覽器組件;此時,應用會選用 Chromium 體系的概率較高。應用選擇自己內置并維護瀏覽器組件的原因有很多,例如以下幾類需求:
-
在瀏覽器內核層回收更多用于 Debug 的客戶端信息;
-
支持如夜間模式、中文優化等用戶需求;
-
支持更多的視頻格式和文件格式;
也有應用為了應對此前 App Store 在 WWDC 大會提出的限制(即 App Store 中的所有應用都必須啟用 App Transport Security 安全功能并全量走 HTTPS),使用改過的 Webview 組件曲線救國,以便達到 App Store 的合規需求。
也因為應用自己維護所使用的瀏覽器組件,當系統的 WebView 跟隨系統升級而修復漏洞時,應用所使用的的瀏覽器組件并不跟著更新;
作為應用開發者自己維護的硬分支,Chromium 不斷的功能變更和漏洞修復補丁都需要應用開發者自行合并和兼容;這不僅需要硬核的瀏覽器研發能力也需要日以繼夜不斷的堅持。
再加上,無論在移動端還是桌面客戶端,在使用應用內 WebView 時為了更加輕便和簡潔,瀏覽器組件多是以單進程的方式啟動;
而在我們之前對 Sandbox 技術的介紹中,瀏覽器 Sandbox 和單進程 WebView 組件顯然是沖突的;
這也使得歷史上關閉 Sandbox 能力的客戶端程序,在漏洞修復過程中,對于開啟 Sandbox 的修復操作存在歷史包袱。
無論如何,我們始終不建議移動端應用的 WebView 組件可以由用戶控制并打開開放性的頁面;
這會使得應用內加載的內容可能存在不可控或不可信的內容。WebView 組件可以打開的 URL,應該用白名單進行限制;特別是可以用 Deeplink 打開并且存在 URL 參數的 WebView。
3.2.2 桌面客戶端
許多桌面客戶端應用也是基于 Chromium 構建的。一類是基于 Chromium 定制的瀏覽器產品、或內置基于 Chromium 開發 Webview 組件的桌面客戶端應用;另一類是基于 Electron 構建的桌面客戶端應用。
前者與傳統 Chrome 瀏覽器或是嵌入在移動客戶端的 Webview 組件類似,如果未開啟沙箱保護,面臨很大的風險。而后者 Electron 則是在評估 Chromium 漏洞攻防利用場景時,比較容易被忽視的一塊。Electron 基于 Chromium 和 Node 構建,其主要特性之一就是能在渲染進程中運行 Node.js。
目前有許多客戶端工具基于它開發,涉及:VS Code、Typora、Slack 等。默認情況下,渲染器進程未受沙箱保護,這是因為:大多數 Node.js 的 API 都需要系統權限,沒有文件系統權限的情況下 require() 是不可用的,而該文件系統權限在沙箱環境下是不可用的,但功能性進程受沙箱保護。?
Electron 除面臨渲染引擎本身的安全風險外,主要風險源自于其本身的功能特性——nodeIntegration。當該選項被設置為 true,表示 renderer 有權限訪問 node.js API,進而執行 “特權” 操作。這時如果攻擊者能自由控制渲染的頁面內容,則可直接實現 RCE。
IV. 風險收斂方案
回到我們今天的主題:修復和防御。
如上我們知道,Chromium 的安全問題是方方面面的,各類安全風險也會在不同的場景上產生,那么如何收斂就是企業安全建設永恒的話題;最后我們想分享我們的安全實踐經驗,力求解答在安全實踐中我們遇到的以下幾個問題,如:
Chrome 組件的漏洞都有哪些?Google 又是如何跟進它們的?我們又該如何評估和檢測 Chrome 持續更新過程中所公開的 1Day 風險?最終如何修復?Linux 容器中開啟 Chrome 沙盒的最佳實踐又是什么?
4.1 風險監測和評估
4.1.1 風險情報
有兩個渠道可以及時了解到 Chromium 漏洞披露情況:
1) Chromium 工單系統
該平臺上收錄了所有已公開的 Chrome 安全 Issue,可借助特定關鍵詞檢索。如檢索已公開的高風險安全問題,可訪問:
2) Chrome 發布日志
Chrome 穩定版本發布消息會在 https://chromereleases.googleblog.com/ 上發出,和穩定版本發布消息一起的還有該版本做了哪些安全更新以及對應漏洞的獎金。
事實上,甲方安全人員還可以借助一些技巧,提前了解安全問題的修復細節。
Gerrit 是基于 git 的一款 Code Review 平臺,chrome team 使用該平臺進行 code review:https://chromium-review.googlesource.com/。該平臺上的主題會關聯對應的 issue id,通過對應修復 commit 的主題可以了解到 issue 的修復方案和代碼。
chromium 使用 https://bugs.chromium.org 對 chromium 的 bug 進行跟蹤。可以用短鏈來訪問對應的 issue,例如 issue 1195777 可以用該鏈接訪問:https://crbug.com/1195777。
chromium 安全問題對應關聯的 issue 在修復期間并且在補丁發布后也不一定是可見的,官方給出的披露原則是在補丁廣泛應用后才會開放 issue 的限制。但是 Gerrit 上對 issue 修復代碼的 code review 和關聯信息是一直可見的,我們如果想了解某個 issue 具體的修復代碼和方案可以在 Gerrit 上找到。
以 issue 1195777 為例,在 Gerrit 使用 bug 搜索關鍵字可以搜到對應 commit 的 code review 主題:

而如果只有 CVE 編號,CVE 的 References 一般會給出 issue 的短鏈,雖然通常該 issue 限制訪問,但是仍可以通過 Gerrit 了解相關 issue 的具體修復代碼,安全研究者可以根據這些修復代碼對該問題進行分析,進而推測出漏洞復現代碼。
難怪 Twitter 上某位研究員會說:“如果 0-Day 有 Chromium Bug Tracker 的編號,那它就不算 0-Day 了”。

4.1.2 風險評估
通常,在 Chromium 官方披露漏洞或外部已出現在野利用的案例后,應進行風險評估,主要聚兩個問題:
-
公司內哪些產品受漏洞影響?
-
外部披露的 exp 是否能真實利用形成危害?
在獲悉一個漏洞的存在后,安全人員需要評估漏洞對公司的影響如何。通常一個可利用的漏洞在披露后會馬上有安全人員寫出 exploit,而公開的 exploit 將導致利用門檻的大幅降低。
因此,常常需要監控公開信息渠道的 exploit 信息,例如:監控 Github、Twitter 等平臺的消息。但是早在 exploit 披露前,就可以通過 Chromium Monorail 系統中的 issues、代碼 CL 或者更新日志提前了解風險。
一個漏洞的影響評估流程可以按下面幾步走:
step 1
確定存在漏洞組件為哪個部分。
step 2
采集使用了該組件的產品(包括:使用了嵌入式瀏覽器的客戶端、單純使用 v8 引擎等組件的軟件、使用了 chrome headless 的服務端程序);
有些產品僅使用 chrome 的一部分組件可能不受影響。例如:v8 就會影響所有用 Chromium 內核的產品,但 iOS 客戶端如果用 JavaScriptCore,則不受影響。
step 3
確認使用存在漏洞組件的產品使用的版本是否受影響,如果產品本身對 chromium 進行定制化開發的情況下,難以根據版本確定,可以通過 PoC(部分場景下,可借助 Chromium 項目中的單元測試用例)進行黑盒測試或者白盒審計受影響代碼是否存在,是否存在漏洞的觸發路徑。
step 4
原則上內存破壞類的漏洞在沒有 exploit 公開的情況下也需要盡快修復,存在公開 exploit 的情況下,需要立即修復;有時候 exploit 使用到的 exploit 技術可能僅適用于某些版本的 chromium,但是并不代表這些版本之外的 chromium 完全沒有利用的可能。
例如使用 WebAssembly 創建 RWX pages 來寫入 shellcode 的技術在客戶端使用的 chromium 版本不支持,但依舊存在通過 ROP 等技術來到達 RCE 的可能性。
4.1.3 風險檢測
4.1.3.1 黑盒測試
V8 等組件會編寫單元測試 js 文件,可以基于此修改形成頁面,來通過黑盒的方式判斷組件是否受對應漏洞影響。對于漏洞測試來說,這個資源也是極好的 TestCase。
以 CVE-2021-21224 為例,編寫黑盒測試用例過程如下:
step 1
通過 Issue 編號定位到對應的 Chromium Gerrit 工單
https://chromium-review.googlesource.com/c/v8/v8/+/2838235
step 2
定位到官方提供的、針對該漏洞的單元測試文件


step 3 基于單元測試文件修改生成黑盒測試用例
如果仔細觀察,會發現上述單元測試代碼中包含 % 開頭的函數。它們是 v8 引擎內置的 runtime 函數,用于觸發 v8 引擎的某些功能特性,需要在 v8 的 debug 版本 d8 命令行工具啟動時,追加 --allow-natives-syntax 參數才會生效。
因此,直接將上述單元測試 js 來測試是無法準確測出是否存在漏洞的。但可以通過編寫 js 代碼,實現相同的效果,例如:

值得一提的是,前述漏洞的單元測試用例并不會造成瀏覽器 tab 崩潰,而只是輸出的數值與預期不符。因此,可以看到上述單元測試用例中引入了 assertTrue、assertEquals 等斷言方法,用于判斷單元測試數值是否與預期相等。
如果不等,則認為存在漏洞。在進行改造時,也要一并用自己的 JavaScript 代碼替換。最終,前述官方提供的測試用例可改造如下:

step 4
最終效果如下


4.1.3.2 靜態代碼掃描
如上面所述,由于 Chrome 漏洞即便在沒有正式發布安全公告前,就已經有 Issue ID,且能通過 Gerrit 平臺找到涉及的代碼變動。因此,開發人員可以搶先在公司內部代碼倉庫進行全局靜態代碼掃描并修復問題。

1. 收集包含 chromium 組件的倉庫
不同的項目可能會引入 Chromium 整體或部分相關的組件,通常可結合文件名、或特定的代碼片段,在公司的代碼倉庫中收集包含相關指紋的倉庫。
2. 精確判斷某個 Issue 對應的代碼是否已修復
以要精準掃描全局代碼倉庫中是否存在涉及 v8 組件的 CVE-2021-21224 的漏洞代碼為例。可基于 semgrep 類方案,對公司代碼倉庫進行全局檢查,編寫靜態代碼掃描步驟如下:
1) 根據 Issue 號找到對應的漏洞修復代碼變動
https://chromium-review.googlesource.com/c/v8/v8/+/2838235
https://chromium-review.googlesource.com/c/v8/v8/+/2838235/4/src/compiler/representation-change.cc
2) 確定涉及文件 representation-change.cc,存在漏洞的代碼特征為

可編寫 semgrep 規則如下

調用命令掃描

最終效果如下

4.1.3.3 主機Agent采集
針對部署在服務器端、且使用了Chromium的程序,除了上述方法之外,可以考慮借助HIDS、EDR或RASP等系統采集進程特征,排查存在風險的實例。
同時滿足下面兩個條件的 cmdline,其進程我們就可以認為是存在風險的:
-
程序名包含 Chrome 或 Chromium
-
且 Cmdline 中包含 --no-sandbox 參數或 --disable-setuid-sandbox
1) 關于誤報
這里大家可能會產生疑問,這里為什么單獨檢測 Sandbox 的開啟與關閉就判斷風險呢?
若Chromium組件已經使用最新發布的commit編譯而成,包含了所有的漏洞補丁,也一樣不會受到1Day和NDay漏洞的影響。
其實,這里主要考慮到Chrome在對漏洞修復是十分頻繁的,持續的升級存在一定的維護成本,且不排除攻擊者擁有Chromium 0Day的可能。相較之下,逃逸Sandbox以控制瀏覽器所在的主機,是比較困難的;所以要求線上業務,盡可能開啟 Chromium Sandbox特性。
2) 關于漏報
另外,以上方案若 Chrome 可執行文件被修改了文件名,則容易產生漏報。另一種可選的方案是:提取出多個 Chrome 的特有選項進行過濾。例如,headless 瀏覽器啟動時一般不會導航至特定 url,此時命令行會存在 about:blank,再用 Chrome 特定的區別于其他瀏覽器的選項進行排除。
更復雜的方案可以提取出 Chrome 執行文件的文件特征,或者建立 Chrome 執行文件的 hashsum 數據庫來判斷進程的執行文件是否是 Chrome 瀏覽器,進而再篩選啟動時用了不安全配置的進程。
其實,我們在大規模觀察相關的進程數據和運營之后,發現利用 --no-sandbox 單個因素進行進程數據分析并獲取未開啟 Sandbox 的 Chromium 進程,這樣簡單粗暴的做法并不會產生太多誤報;有些進程看似非 Chromium 瀏覽器,但其實也集成了 Chromium 并使用 no-sandbox 參數。
4.2 風險修復
4.2.1 通用修復方案
無論是客戶端還是服務端,為了解決 Chrome 漏洞的遠程命令執行風險,啟用 Chrome Sandbox,去除啟動 Chrome 組件時的 --no-sandbox 參數都是必須推進的安全實踐。
如果客戶端程序直接使用了 Chrome 的最新版本,且未進行過于復雜的二次開發和遷移,沒有歷史包袱的話,在客戶端里開啟 Chrome Sandbox,其實就是使用 Chrome 組件的默認安全設計,障礙是比較小的。
此處根據不同場景和需求,存在三種不同的修復方案:
方案 1. 啟用 Sandbox
1.啟動 Chrome 時切勿使用 --no-sandbox 參數,錯誤的例子如:
./bin/chrome --remote-debugging-address=0.0.0.0 --remote-debugging-port=9222 --disable-setuid-sandbox --no-sandbox
2.使用普通用戶而非 root 用戶啟動 chrome headless 進程
方案 2. 更新 Chromium 內核版本(后續維護成本極高)
下載 https://download-chromium.appspot.com/ 中的最新版本進行更新,并在后續迭代中持續升級到最新版
Chromium 的最新版本會編譯最新的 MR 和 Commit,因此也會修復 Chrome 未修復的 0.5Day 漏洞,下載鏈接包含了所有的操作系統的 Chromium ,
例如 Linux 可訪問
https://download-chromium.appspot.com/?platform=Linux_x64&type=snapshots 下載。
請注意,如果不希望相似的安全風險如之前的 Fastjson 那樣需要反復跟進并且高頻推動業務修復,強烈建議安全團隊推動業務參考方案一開啟 Sandbox,方案二可以當成短期方案規避當前風險。
經統計,2010 年至今 Google 共對外公開 Chromium 高危漏洞 1800 多個;Chromium 的漏洞修復十分頻繁,若不開啟 Sandbox,需持續更新最新版本。
若要啟用 Sandbox,需要解決一定的依賴:首先,Chrome 的 Sandbox 技術依賴于 Linux 內核版本,低版本的內核無法使用。各 Sandbox 技術 Linux 內核依賴可參考下圖

圖片來源 官方文檔
Chrome 運行時會尋找 chrome-sandbox 文件,一般下載 Chrome 的 Release 時,Chrome 程序目錄下都包含了 Sandbox 程序,若無法尋找到 chrome-sandbox 文件可能會產生下述 Error 信息:
_[0418/214027.785590:FATAL:__zygote_host_impl_linux.cc__(116)] No usable sandbox! Update your kernel or see_
_https://chromium.googlesource.com/chromium/src/+/master/docs/linux/suid_sandbox_development.md_ _for more information on developing with the SUID sandbox. If you want to live dangerously and need an immediate workaround, you can try using --no-sandbox._
可參考以下鏈接進行配置
若服務器的 Chrome 目錄下包含了 chrome-sandbox 文件,則可以直接修改配置運行,若不包含,可前往 https://download-chromium.appspot.com/ 下載對應版本的 chrome-sandbox 文件使用。
- 注:Chrome 可執行文件的同一目錄內包含 chrome-sandbox 程序,則無需手動設置 CHROME_DEVEL_SANDBOX 環境變量

方案 3. 客戶端選擇系統默認瀏覽器打開外鏈 URL
另外一個更加合適合理的設計是盡量避免使用應用內置的瀏覽器打開開放性 URL 頁面。我們應該盡量使用系統的瀏覽器去打開非公司域名的 URL 鏈接(同時應該注意公司域名下的 URL 跳轉風險);把打開 URL 的能力和場景交還給系統瀏覽器或專門的瀏覽器應用;保障應用內加載的資源都是可控的。
此方案同樣適用于:客戶端內置的 Chromium Webview 組件短時間內無法隨系統快速更新,且由于歷史包袱無法 Webview 組件無法開啟沙箱。
此時,在客戶端引入一個 “降級” 邏輯,將不可信的頁面跳轉交給系統默認的瀏覽器打開。由于系統默認的瀏覽器通常默認是打開沙箱的,因此不失為一種“緩兵之計”。
4.2.2 云原生時代下,針對 Chrome 組件容器化的風險修復指引
業界云原生實踐的發展非常迅速,企業應用容器化、組件容器化的腳步也勢不可擋。從當前的 Kubernetes 應用設計的角度出發,Chrome Headless 組件在邏輯上是非常適用于無狀態應用的設計的,所以 Chrome 組件在容器化的進程也比較快。也因此,在 HIDS 進程大盤中, 啟用 --no-sandbox 的 Chrome headless 進程也一直在持續增多。
如果 Chrome 瀏覽器組件已經實現了容器化,那么您想使用 Chrome sandbox 肯定會遇到各種麻煩;網絡上有很多不完全安全的建議和文檔,請盡量不要給容器添加 privileged 權限和 SYS_ADMIN 權限,這將可能引入新的風險,詳情可參考 TSRC 之前的文章《紅藍對抗中的云原生漏洞挖掘及利用實錄》。
我們應該盡量使用例如 --security-opt 的方案對容器權限進行可控范圍內的限制,構建一個 Seccomp 白名單用于更安全的支持容器場景,這是一個足夠優雅且較為通用的方式。如果企業已經踐行了 K8s 容器集群安全管理的規范和能力,在集群內新建帶有 privileged 權限或 SYS_ADMIN 權限的應用容器是會被集群管理員明確拒絕的,Seccomp 是一個安全且可管理的方案。
你可以參考下述方式啟動一個帶有 seccomp 配置的容器:
docker run -it --security-opt seccomp:./chrome.json chrome-sandbox-hub-image-near --headless --dump-dom https://github.com/neargle
實際上 seccomp 配置文件規定了一個可管理的 syscall 白名單,我們的配置文件就是需要把 Sandbox 所需的系統權限用白名單方式賦予給容器,使得容器可以調用多個原本默認禁止的 syscall。可以使用下列命令來檢測當前的操作系統是否支持 seccomp:
grep CONFIG_SECCOMP= /boot/config-$(uname -r)
CONFIG_SECCOMP=y
如果你的容器使用 K8s 進行部署,那你可以在 spec.securityContext.seccompProfile 中配置上述 chrome.json 文件。

通過白名單設置 Chrome 所需的 syscall 以最小化容器權限,避免容器逃逸的風險,同時也符合多租戶容器集群的安全設計,是一個推薦的方案;設置 Seccomp 后,容器內可正常啟用 chrome-sandbox,如下圖。

根據在 HIDS 收集到的資產和內部操作系統的特性,可以利用 strace 工具很容易收集到啟動 Sandbox 所需的 SysCall,并根據 SysCall 編寫所需的 seccomp 配置文件。
當然直接使用開源社區里現成的配置文件也能適用于絕大部分環境,著名前端測試工具 lighthouse 所用的配置文件是一個非常不錯的參考:
V. 總結
隨著 Chromium 在企業各場景下的廣泛應用,需要針對性地設置風險例行檢測及應急響應方案,涉及的風險與應用場景、檢查及修復方式,可概括如下:

除 Chromium 外,企業開發時也不乏會涉及到 Safari、Firefox 等其他瀏覽器類組件的場景,在進行風險排查和響應時可借鑒類似的思路。
Ⅵ. 參考及引用
[1] Linux Sandboxing
https://chromium.googlesource.com/chromium/src/+/HEAD/docs/linux/sandboxing.md
[2] The Security Architecture of the Chromium Browser
https://seclab.stanford.edu/websec/chromium/chromium-security-architecture.pdf
[3] My Take on Chrome Sandbox Escape Exploit Chain
https://medium.com/swlh/my-take-on-chrome-sandbox-escape-exploit-chain-dbf5a616eec5
[4] Linux SUID Sandbox
https://chromium.googlesource.com/chromium/src/+/HEAD/docs/linux/suid_sandbox.md
[5] How Blink Works
https://docs.google.com/document/d/1aitSOucL0VHZa9Z2vbRJSyAIsAz24kX8LFByQ5xQnUg/edit
[6] Chrome 瀏覽器引擎 Blink & V8
https://zhuanlan.zhihu.com/p/279920830
[7] Blink-in-JavaScript
https://docs.google.com/presentation/d/1XvZdAF29Fgn19GCjDhHhlsECJAfOR49tpUFWrbtQAwU/htmlpresent
[8] core/script: How a Script Element Works in Blink
[9] [TPSA21-12] 關于 Chrome 存在安全問題可能影響 Windows 版本微信的通告
https://security.tencent.com/index.php/announcement/msg/230
[10] Hacking Team Android Browser Exploit 代碼分析
https://security.tencent.com/index.php/blog/msg/87
[12] Android Webview UXSS 漏洞攻防
Ⅶ. 團隊介紹
關于騰訊藍軍
騰訊藍軍(Tencent Force)由騰訊 TEG 安全平臺部于 2006 年組建,十余年專注前沿安全攻防技術研究、實戰演練、滲透測試、安全評估、培訓賦能等,采用 APT 攻擊者視角在真實網絡環境開展實戰演習,全方位檢驗安全防護策略、響應機制的充分性與有效性,最大程度發現業務系統的潛在安全風險,并推動優化提升,助力企業領先于攻擊者,防患于未然。
騰訊藍軍堅持以攻促防、攻防相長,始終與時俱進,走在網絡安全攻防實戰研究的最前沿。未來,騰訊藍軍也將繼續通過攻防多方視角,探索互聯網安全新方向,共建互聯網生態安全。
關于騰訊研發安全團隊
騰訊公司內部與自研業務貼合最緊密的一線安全工程團隊之一。團隊負責軟件生命周期各階段的安全機制建設,包括:制定安全規范 / 標準 / 流程、實施內部安全培訓、設計安全編碼方案、構建安全漏洞檢測(SAST/DAST/IAST)與 Web 應用防護(WAF)系統等。
在持續為 QQ、微信、云、游戲等重點業務提供服務外,也將積累十余年的安全經驗向外部輸出。通過為騰訊云的漏洞掃描、WAF 等產品提供底層技術支撐,助力產業互聯網客戶安全能力升級。
本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/1641/
暫無評論