作者:騰訊湛瀘實驗室
來源:https://weibo.com/ttarticle/p/show?id=2309404351596157885398

0x00 背景

近期谷歌威脅分析團隊(Google's Threat Analysis Group)發現了一例野外攻擊中的Chrome遠程代碼執行漏洞:CVE-2019-5786。攻擊者利用該漏洞配合一個win32k.sys的內核提權(CVE-2019-0808 )可以在win7上穿越Chrome沙箱。野外利用并且帶有沙箱逃逸的Chrome漏洞實屬罕見,因此騰訊安全湛瀘實驗室在谷歌官方發布公告后針對此次攻擊進行了技術還原分析。

由于微軟在windows 7上并未實現win32k Lockdown機制,因此win7系統中的Chrome沙盒并不能充分防御win32k漏洞的利用。關于此次攻擊中的CVE-2019-0808 win32k提權(https://portal.msrc.microsoft.com/en-us/security-guidance/advisory/CVE-2019-0808)我們不作過多介紹,重點來探討CVE-2019-5786這個漏洞的一些細節。

0x01 技術細節

根據谷歌在Chrome3月份的安全更新(https://chromereleases.googleblog.com/2019/03/stable-channel-update-for-desktop.html)中的描述:這是一個FileReader中的Use-after-free漏洞。

在Chrome瀏覽器中,FileReader 可以用來異步讀取存儲在用戶計算機上的文件(或原始數據緩沖區)的內容,使用 File 或 Blob 對象指定要讀取的文件或數據。

FileReader 有三種狀態,如下圖所示:

img

我們在github上查找這個漏洞的補丁信息如下:https://github.com/chromium/chromium/commit/ba9748e78ec7e9c0d594e7edf7b2c07ea2a904499

img

我們看補丁后的代碼:在返回部分result的時候,不再直接返回raw_data_中的緩沖區,而是返回其拷貝。據此可以推測UAF應該是發生在這塊直接返回的內存上。

通常情況下,如果我們構造以下JS片段

let arr1= new ArrayBuffer(0x1000)

let ta1 = new Uint8Array(arr1);

let ta2 = new Uint8Array(arr1);

neuter(arr1);

在上述代碼中,如果ArrayBuffer arr1被分離(detach),即arr1的所有權被轉移到一個worker線程,那么該對象內部的was_detached標志位會被設置,后續TypedArray在使用該對象時候,會先進行檢查。

BIT_FIELD_ACCESSORS(JSArrayBuffer, bit_field, was_detached,

                    JSArrayBuffer::WasDetachedBit)

也還要其他的操作來確保不會出現UAF,代碼片段如下:

img

回到這個漏洞來看,

scoped_refptr<ArrayBuffer> ArrayBufferBuilder::ToArrayBuffer() {

  // Fully used. Return m_buffer as-is.

  if (buffer_->ByteLength() == bytes_used_)

?    return buffer_;



  return buffer_->Slice(0, bytes_used_);

}

raw_data_->ToArrayBuffer()可能會返回內部buffer的拷貝,或者是返回一個指向其內部buffer的智能指針。

ArrayBuffer應該被理解為是獨占其內部的buffer的,在后一種情況下,如果已經結束加載后獲取FileReader的result,raw_data_會被清零;然而,如果在沒有完成加載的情況下,多次獲取FileReader的result,Chrome會創建多個內部引用相同buffer區域的DomArrayBuffer。此時我們通過worker線程釋放其中一個,就可以在主線程中造成UAF。

img

Poc關鍵代碼如下:

   var reader1 = new FileReader();

   // …

   flag = reader1.result;

   flag2 = reader1.result;

   abc = new Uint8Array(flag);

   abc2 = new Uint8Array(flag2);

   neuter(flag);

   //...

   abc2[0] = 1;  //uaf !

以上代碼即可造成ArrayBuffer非常穩定的UAF。熟悉瀏覽器漏洞的同行都了解ArrayBuffer的漏洞很好利用,這里不再對利用方式作進一步討論。

0x02 結論

根據上文的分析可以看到CVE-2019-5786是一個非常高質量的遠程代碼執行漏洞。騰訊安全湛瀘實驗室提醒廣大Chrome用戶盡快將瀏覽器升級到官方最新版。同時,建議國內使用Chrome內核的瀏覽器廠商緊密關注此次更新,主動排查修復風險,保障廣大用戶安全。


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