自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

一個(gè)有關(guān) V8 漏洞的細(xì)節(jié)分析 (一)

安全 漏洞
當(dāng)開發(fā)人員決定使用新的Torque語言重新實(shí)現(xiàn)兩個(gè)CodeStubAssembler(CSA)函數(shù)時(shí),V8中就會(huì)出現(xiàn)漏洞。

當(dāng)開發(fā)人員決定使用新的Torque語言重新實(shí)現(xiàn)兩個(gè)CodeStubAssembler(CSA)函數(shù)時(shí),V8中就會(huì)出現(xiàn)漏洞。這兩個(gè)函數(shù)用于在JavaScript中創(chuàng)建新的FixedArray和FixedDoubleArray對(duì)象,盡管新的實(shí)現(xiàn)乍看之下是有效的,但它們?nèi)鄙僖粋€(gè)關(guān)鍵組成部分:最大長(zhǎng)度檢查,以確保新創(chuàng)建的數(shù)組的長(zhǎng)度不會(huì)超過預(yù)定義的上限。

在一般人看來,這個(gè)缺失的長(zhǎng)度檢查看起來很正常,但對(duì)于攻擊者來說,就可以利用了TurboFan的typer來獲取訪問權(quán)限中的一個(gè)非常強(qiáng)大的利用原語:數(shù)組,其長(zhǎng)度字段遠(yuǎn)大于其容量。該原語為攻擊者提供了V8堆上的越界訪問原語,這很容易導(dǎo)致代碼執(zhí)行。

[[386006]]

漏洞實(shí)現(xiàn)過程

如果要繼續(xù),則需要構(gòu)建V8版本8.5.51(提交64cadfcf4a56c0b3b9d3b5cc00905483850d6559),建議使用完整符號(hào)進(jìn)行構(gòu)建(修改args.gn并添加symbol_level = 2行)。

在x64.release目錄中,你可以使用以下命令以零編譯器優(yōu)化來編譯發(fā)行版本:

  1. find . -type f -exec grep '\-O3' -l {} ";" -exec sed -i 's/\-O3/\-O0/' {} ";" -ls 

如果你想繼續(xù)閱讀本博文中的一些代碼示例,我仍然建議你構(gòu)建普通發(fā)行版(啟用編譯器優(yōu)化)。如果不進(jìn)行優(yōu)化,某些示例將花費(fèi)非常長(zhǎng)的時(shí)間才能運(yùn)行。

從上面鏈接的bugtracker中獲取概念證明。

2017年之前的V8

在2017年之前,許多JavaScript內(nèi)置函數(shù)(Array.prototype.concat,Array.prototype.map等)都是用JavaScript本身編寫的,盡管這些函數(shù)使用了TurboFan(V8的推測(cè)性優(yōu)化編譯器,稍后將進(jìn)行詳細(xì)說明)。為了最大限度地發(fā)揮性能,它們的運(yùn)行速度根本沒有使用本機(jī)代碼編寫的速度快。

對(duì)于最常見的內(nèi)置函數(shù),開發(fā)人員將以手寫匯編形式編寫非常優(yōu)化的版本。之所以可行,因?yàn)镋CMAScript規(guī)范(點(diǎn)擊查看示例)中對(duì)這些內(nèi)置函數(shù)的描述非常詳細(xì)。但是,它有一個(gè)很大的缺點(diǎn):V8針對(duì)大量平臺(tái)和體系結(jié)構(gòu),這意味著V8開發(fā)人員必須為每個(gè)體系結(jié)構(gòu)編寫和重寫所有這些優(yōu)化的內(nèi)置函數(shù)。隨著ECMAScript標(biāo)準(zhǔn)的不斷發(fā)展和新語言函數(shù)的不斷標(biāo)準(zhǔn)化,維護(hù)所有這些手寫程序集變得非常繁瑣且容易出錯(cuò)。

遇到此問題后,開發(fā)人員開始尋找更好的解決方案。直到TurboFan引入V8才找到解決方案。

CODESTUBASSEMBLER

TurboFan為低層指令帶來了跨平臺(tái)的中間表示(IR),V8團(tuán)隊(duì)決定在TurboFan之上構(gòu)建一個(gè)新的前端,他們將其稱為CodeStubAssembler。 CodeStubAssembler定義了一種可移植的匯編語言,開發(fā)人員可以使用該語言來實(shí)現(xiàn)優(yōu)化的內(nèi)置函數(shù)。最重要的是,可移植匯編語言的跨平臺(tái)性質(zhì)意味著開發(fā)人員只需編寫一次內(nèi)置函數(shù)即可。所有支持的平臺(tái)和體系結(jié)構(gòu)的實(shí)際本機(jī)代碼都由TurboFan進(jìn)行編譯,你可以在此處閱讀有關(guān)CSA的更多信息。

盡管這是一個(gè)很大的改進(jìn),但仍然存在一些問題。使用CodeStubAssembler的語言編寫最佳代碼需要開發(fā)人員積累很多專業(yè)知識(shí)。即使掌握了所有這些知識(shí),仍然存在很多容易導(dǎo)致安全漏洞的非常規(guī)漏洞,這導(dǎo)致V8團(tuán)隊(duì)最終編寫了一個(gè)稱為Torque的新組件。

Torque

Torque是基于CodeStubAssembler構(gòu)建的語言前端,它具有類似TypeScript的語法,強(qiáng)大的類型系統(tǒng)和強(qiáng)大的漏洞檢查函數(shù),所有這些使得它成為V8開發(fā)人員編寫內(nèi)置函數(shù)的理想選擇。Torque編譯器使用CodeStubAssembler將Torque代碼轉(zhuǎn)換為有效的匯編代碼,它極大地減少了安全漏洞的數(shù)量,你可以在此處閱讀更多有關(guān)Torque的信息。

漏洞發(fā)生的原因

由于Torque仍相對(duì)較新,因此仍然需要重新實(shí)現(xiàn)大量的CSA代碼。其中包括用于處理創(chuàng)建新的FixedArray和FixedDoubleArray對(duì)象的CSA代碼,它們是V8中的“快”數(shù)組(“快”數(shù)組具有連續(xù)的數(shù)組后備存儲(chǔ),而“慢”數(shù)組具有基于字典的后備存儲(chǔ))。

漏洞利用

開發(fā)人員將CodeStubAssembler :: AllocateFixedArray函數(shù)重新實(shí)現(xiàn)為兩個(gè)Torque宏,一個(gè)用于FixedArray對(duì)象,另一個(gè)用于FixedDoubleArray對(duì)象:

如果將上述函數(shù)與CodeStubAssembler :: AllocateFixedArray變體進(jìn)行比較,則會(huì)發(fā)現(xiàn)缺少最大長(zhǎng)度檢查。

NewFixedArray應(yīng)確保返回的新FixedArray的長(zhǎng)度小于FixedArray :: kMaxLength,即0x7fffffd或134217725。

同樣,NewFixedDoubleArray應(yīng)該根據(jù)FixedDoubleArray :: kMaxLength(為0x3fffffe或67108862)檢查數(shù)組的長(zhǎng)度。

在我們研究如何使用缺少的長(zhǎng)度檢查之前,讓我們先了解一下Sergey是如何Trigger此漏洞的,因?yàn)樗幌駝?chuàng)建一個(gè)大于kMaxLength的新數(shù)組那樣簡(jiǎn)單。

V8中的數(shù)組

現(xiàn)在,我們需要更多地了解V8中數(shù)組的表示方式。

內(nèi)存中的數(shù)組

讓我們以數(shù)組[1、2、3、4]為例,并在內(nèi)存中查看它。你可以通過運(yùn)行帶有--allow-natives-syntax標(biāo)志的V8,創(chuàng)建數(shù)組并執(zhí)行%DebugPrint(array)來獲取其地址來實(shí)現(xiàn)此目的,使用GDB查看內(nèi)存中的地址。

在V8中分配數(shù)組時(shí),它實(shí)際上分配了兩個(gè)對(duì)象。請(qǐng)注意,每個(gè)字段的長(zhǎng)度為4字節(jié)/ 32位:

JSArray對(duì)象是實(shí)際的數(shù)組,它包含四個(gè)重要字段以及其他一些不重要的字段。

  • 映射指針:這決定了數(shù)組的“形狀”,具體來說,它確定數(shù)組存儲(chǔ)哪種元素,以及其后備存儲(chǔ)對(duì)象是什么類型。在這種情況下,我們的數(shù)組存儲(chǔ)整數(shù),后備存儲(chǔ)區(qū)為FixedArray。
  • 屬性指針:指向存儲(chǔ)數(shù)組可能具有的任何屬性的對(duì)象。在本例中,數(shù)組除了長(zhǎng)度以外沒有任何屬性,長(zhǎng)度被內(nèi)聯(lián)存儲(chǔ)在JSArray對(duì)象本身中。
  • 元素指針:指向存儲(chǔ)數(shù)組元素的對(duì)象。這也稱為后備存儲(chǔ),在本例中,后備存儲(chǔ)指向FixedArray對(duì)象,稍后會(huì)詳細(xì)介紹。
  • 數(shù)組長(zhǎng)度:這是數(shù)組的長(zhǎng)度。在研究人員那發(fā)布的概念證明中,這是他將長(zhǎng)度字段覆蓋為0x24242424,然后允許他進(jìn)行越界讀取和寫入。

JSArray對(duì)象的元素指針指向后備存儲(chǔ),這是一個(gè)FixedArray對(duì)象,有兩個(gè)關(guān)鍵的事情要記?。?/p>

  • 不需要考慮FixedArray中的后備存儲(chǔ)長(zhǎng)度,你可以將其覆蓋為任何值,但仍然無法讀取或?qū)懭脒吔纭?/li>
  • 每個(gè)索引存儲(chǔ)在數(shù)組的元素上,內(nèi)存中值的表示形式取決于數(shù)組的“元素種類”,而數(shù)組的“元素種類”則取決于原始JSArray對(duì)象的映射。在本例中,這些值是一個(gè)小的整數(shù),它們是31位整數(shù),其最低位設(shè)置為零。 1表示為1 << 1 = 2,2表示為2 << 1 = 4,依此類推。

元素種類

V8中的數(shù)組也具有“元素種類”的概念,你可以在此處找到所有元素種類的列表,但所有表的基本思想都是一樣的:在V8中每次創(chuàng)建數(shù)組時(shí),都會(huì)用元素種類標(biāo)記它,該種類定義了數(shù)組包含的元素類型。最常見的三種元素如下:

PACKED_SMI_ELEMENTS:數(shù)組被壓縮并且僅包含Smis(31位小整數(shù),第32位設(shè)置為0)。

PACKED_DOUBLE_ELEMENTS:與上面相同,但為雙精度(64位浮點(diǎn)值)。

PACKED_ELEMENTS:與上面相同,但數(shù)組僅包含引用。這意味著它可以包含任何類型的元素(整數(shù),雙精度數(shù),對(duì)象等)。

數(shù)組也可以在元素類型之間進(jìn)行轉(zhuǎn)換,但是轉(zhuǎn)換只能針對(duì)更通用的元素類型,而不能針對(duì)更具體的元素類型。例如,具有PACKED_SMI_ELEMENTS類型的數(shù)組可以轉(zhuǎn)換為HOLEY_SMI_ELEMENTS類型,但不能轉(zhuǎn)換為HOLEY_SMI_ELEMENTS類型,即填充已經(jīng)有孔的數(shù)組中的所有孔都不會(huì)導(dǎo)致轉(zhuǎn)換為壓縮元素類型的變體。

下面的圖表展示了最常見的元素類型的轉(zhuǎn)換格:

我們實(shí)際上只關(guān)心與元素類型有關(guān)的兩件事:

  • SMI_ELEMENTS和DOUBLE_ELEMENTS類型的數(shù)組將其元素存儲(chǔ)在連續(xù)的數(shù)組后備存儲(chǔ)中,作為它們?cè)趦?nèi)存中的實(shí)際表示形式。例如,數(shù)組[1.1、1.1、1.1]會(huì)將0x3ff199999999999a存儲(chǔ)在內(nèi)存中三個(gè)元素的連續(xù)數(shù)組中(0x3ff199999999999a是1.1的IEEE-754表示形式)。另一方面,PACKED_ELEMENTS類型的數(shù)組將存儲(chǔ)對(duì)HeapNumber對(duì)象的三個(gè)連續(xù)引用,這些引用又包含1.1的IEEE-754表示形式。還有基于字典的備份存儲(chǔ)的元素種類,但這不是本文的重點(diǎn)。
  • 因?yàn)镾MI_ELEMENTS和DOUBLE_ELEMENTS類數(shù)組的元素大小不同(Smis是31位整數(shù),而雙精度是64位浮點(diǎn)型值),所以它們也具有不同的kMaxLength值。

概念驗(yàn)證

Sergey提供了兩個(gè)概念證明:第一個(gè)為我們提供了一個(gè)數(shù)組,類型為HOLEY_SMI_ELEMENTS類型,長(zhǎng)度為FixedArray :: kMaxLength + 3,而第二個(gè)為我們提供了一個(gè)數(shù)組,類型為HOLEY_DOUBLE_ELEMENTS類型,長(zhǎng)度為FixedDoubleArray :: kMaxLength + 1。他僅利用第二個(gè)概念證明來構(gòu)造最終的越界訪問原語。

兩種概念證明都使用Array.prototype.concat來首先獲得一個(gè)數(shù)組,該數(shù)組的大小恰好小于相應(yīng)元素類型的kMaxLength值。完成此操作后,將使用Array.prototype.splice向數(shù)組中添加更多元素,這會(huì)導(dǎo)致其長(zhǎng)度增加到kMaxLength以上。之所以可行,是因?yàn)锳rray.prototype.splice的快路徑間接使用了新的Torque函數(shù),如果原始數(shù)組不夠大,則會(huì)分配一個(gè)新數(shù)組。出于好奇,實(shí)現(xiàn)此目的的函數(shù)調(diào)用鏈可能如下:

你可能想知道為什么不能創(chuàng)建一個(gè)大小剛好低于FixedArray::kMaxLength的大數(shù)組并使用它。讓我們嘗試一下(使用優(yōu)化的發(fā)行版等待的時(shí)間會(huì)短一些):

這不僅需要花費(fèi)一些時(shí)間,而且還會(huì)收到OOM(內(nèi)存不足)漏洞!發(fā)生這種漏洞的原因是,數(shù)組分配不會(huì)是一次性完成的。對(duì)AllocateRawFixedArray的調(diào)用很多,每個(gè)調(diào)用都分配一個(gè)稍大的數(shù)組。你可以通過在AllocateRawFixedArray上設(shè)置斷點(diǎn),然后如上所述分配數(shù)組,來在GDB中看到這一點(diǎn)。我不完全確定為什么V8會(huì)這樣做,但是很多分配都會(huì)導(dǎo)致V8很快耗盡內(nèi)存。

我的另一個(gè)想法是改用FixedDoubleArray :: kMaxLength,因?yàn)樗〉枚?使用優(yōu)化的發(fā)行版):

這確實(shí)有效,因?yàn)樗鼤?huì)返回一個(gè)新的HOLEY_DOUBLE_ELEMENTS類型的數(shù)組,其長(zhǎng)度設(shè)置為FixedDoubleArray :: kMaxLength + 1,因此可以使用它代替array .prototype.concat。我相信這樣做的原因是因?yàn)榉峙浯笮?x3fffffd的數(shù)組所需的分配數(shù)量足夠小,以至于不會(huì)不會(huì)導(dǎo)致引擎進(jìn)入OOM。

但是,此方法有兩個(gè)缺點(diǎn):分配和填充龐大的數(shù)組需要花費(fèi)大量時(shí)間,因此在漏洞利用中并不理想。另一個(gè)問題是,嘗試在內(nèi)存受限的環(huán)境(例如舊手機(jī))中以這種方式Trigger漏洞,可能會(huì)導(dǎo)致引擎運(yùn)行OOM。

另一方面,Sergey的第一個(gè)概念證明在我的計(jì)算機(jī)上花費(fèi)了大約2秒鐘,并且內(nèi)存效率很高。以下是具體分析過程。

第一個(gè)概念證明

第一個(gè)概念證明如下,請(qǐng)確保你使用優(yōu)化的發(fā)行版版本來運(yùn)行它,否則將需要很長(zhǎng)時(shí)間才能完成:

讓我們一步一步來分析,在[1]的位置,創(chuàng)建了一個(gè)大小為0x80000的數(shù)組,并使用1填充。這種大小的數(shù)組需要分配大量?jī)?nèi)存,但幾乎沒有使引擎成為OOM的條件。由于數(shù)組最初是空的,因此它得到的是HOLEY_SMI_ELEMENTS類型,即使將其填充為1也會(huì)保留該元素的類型。

我們稍后會(huì)回到[2],但是在[3]中,使用0xff元素創(chuàng)建了一個(gè)新的args數(shù)組,每個(gè)元素都被設(shè)置為在[1]處創(chuàng)建的數(shù)組。這使args數(shù)組總共為0xff * 0x80000 = 0x7f80000個(gè)元素。在[4]處,將另一個(gè)大小為0x7fffc的數(shù)組壓入args數(shù)組,這使其總數(shù)為0x7f80000 + 0x7fffc = 0x7fffffc個(gè)元素,0x7fffffc僅比FixedDoubleArray :: kMaxLength = 0x7fffffd小1。

在[5],Array.prototype.concat.apply將args數(shù)組中的每個(gè)元素連接到空數(shù)組[],你可以在此處閱讀有關(guān)Function.prototype.apply()如何工作的更多信息,但它實(shí)際上將args視為參數(shù)數(shù)組,并將每個(gè)元素連接為最終的數(shù)組。我們知道元素總數(shù)為0x7fffffc,因此最終數(shù)組將具有那么多元素。這種連接發(fā)生得比較快(在我的設(shè)備上大約需要2秒鐘),盡管它比我前面演示的簡(jiǎn)單地創(chuàng)建數(shù)組要快得多。

最后,在[6]處,Array.prototype.splice向該數(shù)組追加了4個(gè)額外的元素,這意味著其長(zhǎng)度現(xiàn)在為0x8000000,即FixedArray :: kMaxLength + 3。

唯一需要說明的是[2],其中將屬性添加到原始數(shù)組。要了解這一點(diǎn),你必須首先了解幾乎所有V8內(nèi)置函數(shù)的約定是有一個(gè)快路徑和一個(gè)慢路徑。在Array.prototype.concat的情況下,采用慢路徑的一種簡(jiǎn)單方法是向要連接的數(shù)組添加屬,快路徑具有以下代碼:

可以看到,快路徑檢查確保最終數(shù)組的長(zhǎng)度不超過kMaxLength值。由于FixedDoubleArray::kMaxLength是FixedArray::kMaxLength的一半,所以上述概念證明將永遠(yuǎn)不會(huì)通過此檢查。隨意嘗試在不使用array.prop = 1的情況下運(yùn)行代碼;看看會(huì)發(fā)生什么!

另一方面,慢路徑(Slow_ArrayConcat)沒有任何長(zhǎng)度檢查(但是,如果長(zhǎng)度超過FixedArray :: kMaxLength,它仍然會(huì)崩潰并產(chǎn)生致命的OOM漏洞,因?yàn)樗{(diào)用的其中一個(gè)函數(shù)仍然會(huì)檢查長(zhǎng)度。這就是為什么研究者會(huì)使用慢路徑的原因,因?yàn)榭梢岳@過快路徑中存在的檢查。

第二個(gè)概念證明(第一部分)

盡管第一個(gè)概念證明演示了漏洞,并且可以用于利用(在第二個(gè)概念證明中,你只需稍微修改一下trigger函數(shù)),但它需要幾秒鐘才能完成,這可能也不太理想。Sergey選擇使用HOLEY_DOUBLE_ELEMENTS類數(shù)組。這可能是因?yàn)镕ixedDoubleArray::kMaxLength值明顯小于它的FixedArray變體,從而導(dǎo)致更快的Trigger。如果你理解了第一個(gè)概念證明,,那么第二個(gè)概念證明的第一部分的以下注釋版本就很好理解了:

此時(shí),giant_array的長(zhǎng)度為0x3ffffff,即FixedDoubleArray :: kMaxLength +1?,F(xiàn)在的問題是,我們?nèi)绾卧诼┒蠢贸绦蛑惺褂么藬?shù)組?我們沒有任何有用的原語,因此我們需要找到引擎的其他部分,這些部分的代碼取決于數(shù)組長(zhǎng)度不能超過kMaxLength值。

對(duì)于大多數(shù)研究人員來說,該漏洞本身確實(shí)很容易被發(fā)現(xiàn),因?yàn)槟阒恍枰獙⒑瘮?shù)的新的Torque實(shí)現(xiàn)與舊的實(shí)現(xiàn)進(jìn)行比較即可。盡管知道如何利用它,但需要對(duì)V8本身有更深入的了解。 Sergey采取的利用途徑利用了V8的推測(cè)性優(yōu)化編譯器TurboFan,它需要自己引入。

本文翻譯自:https://www.elttam.com/blog/simple-bugs-with-complex-exploits/#content

 

責(zé)任編輯:趙寧寧 來源: 嘶吼網(wǎng)
相關(guān)推薦

2021-08-29 18:34:44

編譯V8C++

2022-05-06 23:03:48

V8CPUProfiler

2022-08-19 06:40:02

V8GC

2015-02-10 14:32:37

XSS漏洞XSS

2022-05-24 06:04:19

ExtensionV8Node.js

2023-10-10 10:23:50

JavaScriptV8

2021-05-28 05:30:55

HandleV8代碼

2009-07-20 09:36:04

谷歌瀏覽器安全漏洞

2020-08-31 08:11:01

V8 8.5Promise前端

2010-07-20 16:35:52

V8JavaScript瀏覽器

2023-06-07 16:00:40

JavaScriptV8語言

2022-09-16 08:32:25

JavaC++語言

2023-06-05 16:38:51

JavaScript編程語言V8

2016-03-03 14:29:15

2014-11-26 09:51:24

GithubGoogleV8

2011-07-18 13:34:44

SQL Server數(shù)拼接字符串

2014-10-21 11:11:08

Siri人工智能

2012-11-07 13:05:29

2022-04-29 08:00:51

V8垃圾回收

2010-08-31 11:42:03

DB2MDC
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)