作者:啟明星辰ADLab
1. 前言
WebKit 是一個開源的瀏覽器引擎,不僅應用在很多主流瀏覽器(Safari,Chrome,UCbrowser,QQBrowser等)上,而且支持Android,iOS,Windows,Linux,macOS等多種平臺上的有關web渲染引擎的應用。
啟明星辰ADLab對WebKit引擎進行漏洞挖掘和代碼審計工作,發現webkit的若干漏洞,都已提交廠商進行修復。
本文將介紹webkit架構和各模塊功能,并詳細分析webkit各模塊的漏洞案例,對 WebKit瀏覽器漏洞面進行一個較為全面的闡述。
2. Webkit架構和模塊
下圖是WebKit的架構和模塊圖。

- WebKit主要包含JavaScritCore,WebCore和Web Template Fundation等主要模塊。其中,WebCore主要功能是加載和渲染網頁,具體包括HTML解析器,CSS解析器, SVG以及DOM等模塊。
- JavaScriptCore是WebKit默認的JavaScript引擎,主要包括低級解釋器LLInt,基線JIT Baseline JIT, 低延遲優化的DFG JIT, 高通量優化的FTL JIT,WebAssembly等模塊。
- Garbage Collection,即垃圾回收,常用在JavaScript、Java等高級語言中。
- Web Template Fundation提供了多種基本庫,類似STL,包括容器,字符串庫,智能指針,以及線程管理基礎等。
WebKit中的每個模塊都可能成為漏洞的重災區,下面我們選取WebKit模塊中的漏洞案例進行詳細分析,其中包括了今年ADLab提交的漏洞。
2.1 WebCore :CVE-2018-12293 等多個整數溢出
CVE-2018-12293是ADLab在6月份提交的WebCore渲染引擎相關的整數溢出漏洞,該漏洞存在于ImageBufferCario.cpp 的WebCore::getImageData函數中。該函數根據可控的width和height屬性的乘積創建數組result:

當width和height足夠大,它們的乘積就會導致整數溢出;當傳遞給創建函數的length大小為0時,緩存的創建并不會受影響,根據ArrayBuffer.cpp:108,申請數組的大小是0時程序會將分配的長度設置為1。
在頁面渲染之前,會先根據前面創建的數組以及width的大小計算destRows緩存的偏移:

顯然此時destRows已經是越界索引,但后面的循環過程會不斷地向其后填充顏色值,導致堆溢出:

漏洞補丁中修復了多處潛在的整數溢出。針對本漏洞,檢查width和height屬性的乘積是否溢出;檢查橫向坐標以及縱向坐標結束的位置的溢出;另外,加入對行數和列數的檢查,預防其他的溢出問題:

2.2 runtime:CVE-2016-4622 回調導致越界訪問
JavaScriptCore的runtime是為JavaScript的運行提供支撐的代碼。在JavaScriptCore中標有“JSC_HOST_CALL”的函數均與JavaScript函數對應。例如arrayProtoFuncSlice與Array對象的slice()函數對應,其調用方法形如:

函數參數可以用一個表達式代替,因此slice函數內部可以形成一個回調,形如:

漏洞CVE-2016-4622產生的根本原因是沒有妥善處理可能的回調。代碼 邏輯中首先獲取了Array的長度,然后在獲取slice()的end參數時動態地改變了該Array的長度,使得end > length,但之后使用fastSlice時仍然根據end參數進行內存拷貝,導致越界訪問。

針對本漏洞,開發者在fastSlice之前添加了檢查Array的長度的代碼,若其已被修改則不再使用fastSlice。這樣就修復了這個漏洞。
2.3 JIT:CVE-2017-2547 DFG優化導致邊界檢查失敗
為了平衡JavaScript的功能與運行效率,WebKit的JavaScriptCore選擇了分層JIT編譯優化的策略。JavaScriptCore由Lexer、Parser、LLInt、Baseline JIT、DFG JIT以及FTL JIT組成。其工作流程如下圖:

- Lexer將輸入的字符串分割成詞素,然后將詞素分成token類;Parser在此基礎上建立相應的語法樹;LLInt執行Parser生成的字節碼。
- 當函數被調用6次、循環至少100次,或者兩者的結合,OSR(On-Stack-Replacement)到Baseline JIT。LLInt和Baseline JIT分析收集到的信息,如最近加載的參數值,返回值等,為下一層優化提供推斷信息。
- 當函數被執行至少60次、循環至少1000次,OSR到DFG JIT。DFG JIT會根據底層收集的分析信息執行類型推斷,消除了許多類型檢查。處理失敗時會OSR回退到BaseLine JIT。
- 當函數執行幾千次或者循環幾萬次,程序會OSR到FTL JIT,執行更進一步的優化。
CVE-2017-2547是WebKit JIT優化漏洞中的典型,這個漏洞發生在DFG JIT的邊界檢查中。DFG對數組邊界檢查時,首先存儲數組訪問的最大邊界值和最小邊界值的范圍,然后遍歷節點,以便每次訪問時總是檢查訪問數組索引的最大值和最小值的節點是否越界,從而刪除其他不必要的訪問節點的檢查。這在邏輯上是合乎情理的:

但當輸入是整數值的時候,代碼邏輯會進入下面的if模塊。其中最小節點被清0;在后續添加數組邊界檢查時,只添加了對最大邊界的檢查,而忽略了最小邊界。因此,同時使用負值索引和正值索引訪問數組,負值部分的訪問會直接繞過DFG生成代碼的數組邊界檢查,達到越界訪問的效果。

漏洞的補丁加入了針對“最小邊界為負值”的判斷。如果滿足條件,DFG會直接OSR回退:

2.4 Garbage Collection:CVE-2017-2491 垃圾回收使用錯誤導致Use-After-Free
垃圾回收過程中,程序從所有的根出發尋找對象被引用情況,如果某對象存在引用則被標記為活動對象,否則相應的內存空間應該被釋放。WebKit中定義的根包括進程棧、JavaScript執行環境棧、MarkedArgumentBuffer。
漏洞CVE-2017-2491涉及對垃圾回收的錯誤使用。在CachedCall中漏洞代碼使用Vector<JSValue>類型的變量存儲函數調用所需參數。例如正則表達式的replace函數,傳入其中的參數可能是大量的,這時代碼只能使用Vector或類似的結構來接收參數。但內存壓力觸發垃圾回收時,Vector無法被垃圾回收算法標記,導致相關內存被錯誤釋放。
之后,開發者使用MarkedArgumentBuffer替換Vector對象,因此該漏洞得到修復:

2.5 WebAssembly:CVE-2018-4121 wasm文件解析導致越界寫
WebAssembly是一種新興的Web技術,它嘗試通過字節碼標準解決JavaScript的運行效率問題。WebAssembly模塊在WebKit中受JavaScriptCore控制,其字節碼通過wasm文件傳遞。wasm文件類似PE文件有不同的區段,例如Type、Import、Function、Table、Code、Data等。WebAssembly要求每種區段在wasm文件中最多出現一次。
漏洞CVE-2018-4121的PoC是一個wasm文件,其中含有兩個Function段。WebKit JavaScriptCore在解析PoC時,只為Function段準備了一個Vetctor來保存函數列表的簽名,且使用uncheckedAppend分兩次把不同Function段的內容附加到同一個Vector。如果第一次可以把Vector裝滿,第二次就能導致越界寫發生。

WebAssembly要求Known區段的所有種類的id順序遞增,例如Function區段的id為3,Import區段的id為2,則Function區段必須位于Import區段的后面;Custom區段不屬于Known,其id為0,因此可以不遵循上述遞增規則。代碼在validateOrder函數想當然地表達了這個規則:

代碼會使Custom區段后面的任意區段通過檢查,這是漏洞產生的根本原因。
為了修補這個漏洞,開發者通過定義不存在的區段Section::Begin(id定義為0),把Custom區段和最初始的情況區別開來:

同時使用previousKnownSection代替previousSection,這樣validateOrder函數的previousKnownSection參數不再包含Custom區段,只處理Known區段來保證其遵循id的“順序遞增”規則,從而修補了這個漏洞:

參考鏈接
[1] https://webkit.org/
[2] https://github.com/WebKit/webkit
[3] https://trac.webkit.org/wiki/JavaScriptCore
[4] https://webkit.org/blog/3362/introducing-the-webkit-ftl-jit/
[5] https://www.geeksforgeeks.org/mark-and-sweep-garbage-collection-algorithm/
[6] https://webassembly.org/docs/binary-encoding/
啟明星辰積極防御實驗室(ADLab)
ADLab成立于1999年,是中國安全行業最早成立的攻防技術研究實驗室之一,微軟MAPP計劃核心成員。截止目前,ADLab通過CVE發布Windows、Linux、Unix等操作系統安全或軟件漏洞近400個,持續保持國際網絡安全領域一流水準。實驗室研究方向涵蓋操作系統與應用系統安全研究、移動智能終端安全研究、物聯網智能設備安全研究、Web安全研究、工控系統安全研究、云安全研究。研究成果應用于產品核心技術研究、國家重點科技項目攻關、專業安全服務等。

本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/660/
暫無評論