# 探究利用 Sentinel Value 突破 Chrome V8 防護機制Sentinel value 是算法中一種特殊值,通常用作循環或遞歸算法的終止條件。Chrome 源碼中存在多種 Sentinel value。之前有研究表明,通過泄露 TheHole 對象可實現某些 CVE 的沙箱內任意代碼執行。谷歌團隊在我們發文闡述該緩解繞過約一周後,迅速將相關 CVE 更新到了 GitHub 上。從 Chrome 源碼可以看到針對 TheHole 對象導致任意代碼執行的緩解修復。但實際上,V8 中還有很多其他不應泄露到 JS 中的原生對象。本文將討論 Uninitialized Oddball 對象,該繞過方法最早出現在 Issue1352549 中。值得注意的是,目前該方法仍可用於最新版 V8,谷歌尚未針對此進行修復。該方法具有較強通用性:1. Issue1216437(CVE-2021-30551)中首次給出的 POC 即爲泄露 internal uninitialized oddball。2. Issue1314616(CVE-2022-1486)中的 POC 也直接泄露了 UninitializedOddball。3. Issue1352549(NoCVE)的影響不容忽視。這些都充分說明了有必要重新審視可能受 PatchGap 影響的軟件。## V8 中的 Sentinel ValueV8 的大部分原生對象定義在 v8/src/roots/roots.h 文件中,它們在內存中相鄰排布。一旦這些不應泄露的原生對象被泄露到 JavaScript 中,就可能導致沙箱內任意代碼執行。爲驗證該方法在最新版 V8 中的有效性,我們可以修改 V8 的原生函數 %TheHole(),使其返回 Uninitialized Oddball。## 繞過 HardenType Issue1352549 中給出了完整代碼,我們對其進行提取和簡化後,在 V8 11.0.0 中測試仍可實現相對任意讀。對優化後的 JavaScript read 函數反匯編,可以看到在檢查 obj.prop 時,沒有檢查以 obj.prop 爲 key 的 Value,而是直接按 JavaScript 語義計算偏移獲取數組值。這導致了在計算時發生類型混淆,實現任意讀。當傳入 uninitialized_oddball 時,以 obj 爲起點計算,最終在 vmovsd xmm0,[r9+r11*8+0x7] 指令中完成任意讀,數據保存在 xmm0 寄存器中。由於 uninitialized_oddball 在 V8 內存中排序靠前且更原始,僞造更容易,是繞過的首選方法。任意寫可參考 Issue1352549 構造分析。修復建議是在優化後的函數返回數組元素時,添加對數組 map 的檢查,避免直接計算偏移返回數組值。## PatchGap 警告分析 Issue1352549 後,我們排查了可能存在 PatchGap 的軟件,發現 Skype 至今未修復該漏洞。x86 下的任意讀寫略有不同,由於沒有地址壓縮,是直接相對整個進程的。在 Skype 的利用中,雖然開啓了 ASLR,但由於文件過大,黑客只需對某個固定地址讀寫,就很可能讀寫到 Skype 文件內容。結合 PE 解析等傳統思路,不難完成整個漏洞利用鏈。這次 PatchGap 不僅涉及 Issue1352549,新繞過方法的公開還導致類似 Issue1314616 和 Issue1216437 的利用難度大幅降低。黑客幾乎無需研究成本,就可實現以往任何泄露 uninitialized_oddball 漏洞的完整利用。## 總結本文簡要討論了通過泄露 uninitialized_Oddball 實現任意讀原語。V8 中還有很多其他 Sentinel value,測試時也容易遇到非 int3 的崩潰。既然 Uninitialized_Oddball 和 TheHole 均可繞過 V8 防護,其他 Sentinel value 也可能存在類似問題。這給我們一些啓示:1. 其他 uninitialized_Oddball 泄露是否也可輕鬆實現 V8 的 RCE。2. 谷歌迅速修復了 TheHole 繞過,但利用垃圾回收繞過 ASLR 的問題長期擱置,說明類似 issue 是否被視爲正式安全問題仍存在模糊邊界。3. 如果將其視爲正式安全問題,fuzzer 中是否有必要考慮將 %TheHole/uninitialized_Oddball 等 Sentinel value 作爲變量加入,以挖掘其他利用原語。無論該類問題是否被正式視爲安全問題,它都會大大縮短黑客實現完整利用的週期。
V8引擎Sentinel Value漏洞探究:繞過防護實現任意代碼執行
探究利用 Sentinel Value 突破 Chrome V8 防護機制
Sentinel value 是算法中一種特殊值,通常用作循環或遞歸算法的終止條件。Chrome 源碼中存在多種 Sentinel value。之前有研究表明,通過泄露 TheHole 對象可實現某些 CVE 的沙箱內任意代碼執行。谷歌團隊在我們發文闡述該緩解繞過約一周後,迅速將相關 CVE 更新到了 GitHub 上。
從 Chrome 源碼可以看到針對 TheHole 對象導致任意代碼執行的緩解修復。但實際上,V8 中還有很多其他不應泄露到 JS 中的原生對象。本文將討論 Uninitialized Oddball 對象,該繞過方法最早出現在 Issue1352549 中。值得注意的是,目前該方法仍可用於最新版 V8,谷歌尚未針對此進行修復。
該方法具有較強通用性:
Issue1216437(CVE-2021-30551)中首次給出的 POC 即爲泄露 internal uninitialized oddball。
Issue1314616(CVE-2022-1486)中的 POC 也直接泄露了 UninitializedOddball。
Issue1352549(NoCVE)的影響不容忽視。
這些都充分說明了有必要重新審視可能受 PatchGap 影響的軟件。
V8 中的 Sentinel Value
V8 的大部分原生對象定義在 v8/src/roots/roots.h 文件中,它們在內存中相鄰排布。一旦這些不應泄露的原生對象被泄露到 JavaScript 中,就可能導致沙箱內任意代碼執行。
爲驗證該方法在最新版 V8 中的有效性,我們可以修改 V8 的原生函數 %TheHole(),使其返回 Uninitialized Oddball。
繞過 HardenType
Issue1352549 中給出了完整代碼,我們對其進行提取和簡化後,在 V8 11.0.0 中測試仍可實現相對任意讀。
對優化後的 JavaScript read 函數反匯編,可以看到在檢查 obj.prop 時,沒有檢查以 obj.prop 爲 key 的 Value,而是直接按 JavaScript 語義計算偏移獲取數組值。這導致了在計算時發生類型混淆,實現任意讀。
當傳入 uninitialized_oddball 時,以 obj 爲起點計算,最終在 vmovsd xmm0,[r9+r11*8+0x7] 指令中完成任意讀,數據保存在 xmm0 寄存器中。
由於 uninitialized_oddball 在 V8 內存中排序靠前且更原始,僞造更容易,是繞過的首選方法。任意寫可參考 Issue1352549 構造分析。
修復建議是在優化後的函數返回數組元素時,添加對數組 map 的檢查,避免直接計算偏移返回數組值。
PatchGap 警告
分析 Issue1352549 後,我們排查了可能存在 PatchGap 的軟件,發現 Skype 至今未修復該漏洞。x86 下的任意讀寫略有不同,由於沒有地址壓縮,是直接相對整個進程的。
在 Skype 的利用中,雖然開啓了 ASLR,但由於文件過大,黑客只需對某個固定地址讀寫,就很可能讀寫到 Skype 文件內容。結合 PE 解析等傳統思路,不難完成整個漏洞利用鏈。
這次 PatchGap 不僅涉及 Issue1352549,新繞過方法的公開還導致類似 Issue1314616 和 Issue1216437 的利用難度大幅降低。黑客幾乎無需研究成本,就可實現以往任何泄露 uninitialized_oddball 漏洞的完整利用。
總結
本文簡要討論了通過泄露 uninitialized_Oddball 實現任意讀原語。V8 中還有很多其他 Sentinel value,測試時也容易遇到非 int3 的崩潰。既然 Uninitialized_Oddball 和 TheHole 均可繞過 V8 防護,其他 Sentinel value 也可能存在類似問題。
這給我們一些啓示:
其他 uninitialized_Oddball 泄露是否也可輕鬆實現 V8 的 RCE。
谷歌迅速修復了 TheHole 繞過,但利用垃圾回收繞過 ASLR 的問題長期擱置,說明類似 issue 是否被視爲正式安全問題仍存在模糊邊界。
如果將其視爲正式安全問題,fuzzer 中是否有必要考慮將 %TheHole/uninitialized_Oddball 等 Sentinel value 作爲變量加入,以挖掘其他利用原語。
無論該類問題是否被正式視爲安全問題,它都會大大縮短黑客實現完整利用的週期。