Mark Vincent Yason(IBM X-Force Advanced Research)
譯:xd0ol1(知道創宇404實驗室)

原文鏈接:https://www.blackhat.com/docs/us-15/materials/us-15-Yason-Understanding-The-Attack-Surface-And-Attack-Resilience-Of-Project-Spartans-New-EdgeHTML-Rendering-Engine-wp.pdf

目錄

0 摘要

EdgeHTML是Windows 10中引入的下一代網頁瀏覽器(代號Spartan)所用的新渲染引擎,因其使用廣泛 - 涵蓋移動端到PC端,故理解它的攻擊面和相應防護措施是很重要的。

在本文中,我們將討論EdgeHTML的攻擊面并對各攻擊維度進行枚舉,同時,我們還會闡述一種用于比較EdgeHTML和MSHTML的方法,以此了解fork過程中所發生的變化,當然更為重要的是發掘可能被攻擊的新特性和新增內部函數。最后,我們將討論相關的漏洞利用防護措施,即它們是如何防御特定類型漏洞的,此外,還會討論那些目前仍然適用的繞過技術。

1 引言

EdgeHTML[1, 2]是微軟Edge瀏覽器(早前代號為Project Spartan)中新引入的渲染引擎,它是目前Internet Explorer中在用的Trident(MSHTML)渲染引擎的一個fork,主要為了支持現有的Web標準以及刪除其中陳舊的代碼。

據估計[3]fork過程中大約有超過22萬行代碼被刪除,并重新添加了大約30萬行代碼用于程序互操作的修繕與新功能的實現。站在安全研究的角度看,理解這些變化所帶來的影響,換言之渲染引擎在攻擊面上的變化,是既有趣而又重要的 - 新的攻擊維度是什么?攻擊者先前使用的一些方式還有效嗎?另一個需要重點理解的方面是新渲染引擎應對攻擊時的防護措施 - 漏洞利用的保護策略是否有變化?默認設置下與MSHTML相比攻擊者進行利用的難度有多大?回答這些基本問題正是本文的目的所在。

接下去的內容分為三大塊。第一部分(概述)將簡要介紹漏洞利用的攻擊面和防護措施,后面還會再進行深入的探討,其中給出的“EdgeHTML攻擊面及其防護”示意圖可作為本文余下篇幅的參考,此外,這部分還討論了我在早前研究過程中用于比對EdgeHTML和MSHTML的方法。第二部分(漏洞利用攻擊面)我們將深入分析組成EdgeHTML攻擊面的那些不同攻擊維度,并指出從MSHTML到EdgeHTML后重要攻擊維度的變化情況。而在最后一部分(漏洞利用防護措施)我們將討論不同的保護策略,它們都有助于增大EdgeHTML引擎上進行漏洞利用的難度和代價。

另外,本文的分析是基于64位Windows 10 build 10240系統中的Edge瀏覽器展開的(edgehtml.dll版本號為11.0.10240.16384)。

2 概述

在深入解讀EdgeHTML引擎的攻擊面與防護措施相關細節前,本節先來做個簡要的介紹,同時本節還將討論EdgeHTML和MSHTML的比較方法,這能幫助我們找出代碼中的主要變化。

2.1 攻擊面及其防護簡介

EdgeHTML引擎模塊(%System32%\edgehtml.dll)負責解析和渲染網頁中各種潛在的惡意內容,它屬于Edge瀏覽器的內容處理單元(MicrosoftEdgeCP.exe),該單元是一個64位的AppContainer沙箱進程。

這里的攻擊面圖示給出了EdgeHTML引擎所接受的不同輸入類型以及負責處理它們的各EdgeHTML類,注意這些類只是相應解析或處理過程的初始入口,其中一些可能還需要借助額外的EdgeHTML類。此外,圖示還列出了EdgeHTML類用于處理輸入時所依賴的函數庫。

對于HTML,EdgeHTML會使用內部的解析器來處理標記,而對基于XML的標記(XHTML,SVG,XML),引擎會額外使用XmlLite進行解析,且如果標記中有引用XSL樣式表,那么引擎會首先通過MSXML6對XML進行轉換,然后才將輸出內容交給標記處理單元,至于CSS的解析同樣也由內部解析器處理。對于圖像的解碼,EdgeHTML主要依賴于Windows Imaging Component (WIC),而對于音頻/視頻內容的解碼,EdgeHTML則主要依賴Media Foundation (MF),同時,用于音頻/視頻字幕的計時文本軌道文件是由EdgeHTML的內部解析器負責處理的,當然這其中還需要借助XmlLite。而字體渲染則會通過DirectWrite進行處理。另外,由標記標簽的解析或經由動態創建所生成的DOM對象會通過DOM API暴露出來,其中一些DOM對象可能需要依賴相應函數庫來實現它們的功能。此外,EdgeHTML引擎在默認情況下還可實例化內置或預安裝的渲染器 - 例如,用于處理PDF內容的WinRT PDF渲染器,以及用于處理Flash內容的Adobe Flash Player程序。

EdgeHTML渲染引擎所處的64位內容處理進程中用到了多種漏洞利用的防護措施,其中就包括了ASLR保護(高熵且強制啟用ASLR)、DEP保護和AppContainer進程隔離保護。并且EdgeHTML及其依賴在編譯時均采用了棧緩沖區安全檢查保護技術(/GS)和最新引入的執行流保護技術(CFG)。此外,例如虛表保護(VTGuard)以及新的內存垃圾回收機制(MemGC)等額外措施也被專門用于EdgeHTML的防護。

2.2 初窺:EdgeHTML和MSHTML的比對

當我一開始對EdgeHTML進行研究的時候就很想知道從MSHTML到EdgeHTML的fork過程中代碼的主要變化是什么。由于類和命名空間能夠表征一組相關的代碼,而這些代碼又反過來對應著程序的某一特性,因此,我嘗試的方法是借助IDAPython枚舉函數或變量名,然后提取其中的命名空間部分,接著去除那些重復項并對得到的結果進行排序,最后,通過diff工具對得到的MSHTML和EdgeHTML命名空間列表進行比較:

來看一個比對結果的例子,如下EdgeHTML中的刪除類表明了引擎在WMF和EMF圖像格式支持上的變化(詳見3.3小節):

-CImgTaskEmf
-CImgTaskWmf

而從另一比對結果的例子可看出CFastDOM下又新增了命名空間,即通過DOM API導出了新的DOM對象類型(詳見3.5小節):

+CFastDOM::{…more…}
+CFastDOM::CXPathEvaluator
+CFastDOM::CXPathExpression
+CFastDOM::CXPathNSResolver
+CFastDOM::CXPathResult
+CFastDOM::CXSLTProcessor

最后,再看一個有意思的比對結果,如下表明其中的一些代碼是從Blink渲染引擎[4,5](Blink是從WebKit的WebCore部分fork來的,大部分的命名空間已從“WebCore”重命名為“blink”)移植過來的:

+blink::WebThread
+WebCore::AnalyserNode
+WebCore::AudioArray<float>
+WebCore::AudioBasicInspectorNode
+WebCore::Audio{…more…}

進一步分析可知這部分移植代碼主要用于EdgeHTML引擎中對Web音頻的支持。

另外,除了用于比較命名空間,這個基本的方法還可用于函數名、類方法名(以識別新的或移除的類功能)、字符串(可給出新功能的描述 - 例如:日志字符串)、導入表(以識別新的依賴庫、用到的特定API)和導出表的比對。

使用此方法時需要留意命名空間被重命名的情況,這會導致比對結果中命名空間的添加及刪除,因此需要做進一步的驗證,該方法還要求相關的符號文件是可用的。此外,二進制的比對[7]則是識別兩個二進制文件間差異的另一選擇。

3 漏洞利用攻擊面

在本節,我們將列舉EdgeHTML引擎所處理的不同輸入以及與此相關的代碼接口。需要注意的是給出的EdgeHTML類僅是解析或處理時的初始入口點,其中一些可能還依賴額外的類來進行處理,獲取這些類的目的在于當我們需要了解引擎是如何處理特定的輸入類型時可借助它們來設置斷點。例如,若要了解基于XML的標記其預解析時的工作原理,則可通過以下方式設置CXmlPre類中的斷點:

(WinDbg)> bm edgehtml!CXmlPre::*

此外,如果引擎依賴其它函數庫來處理特定的輸入類型,那么此函數庫和用到的特定接口也會被列出來。

3.1 標記/樣式的解析

渲染引擎的主要任務之一是處理標記和樣式,對于HTML和CSS,EdgeHTML引擎依靠其內部類進行解析,而對基于XML的標記,引擎則借助XmlLite [8]和MSXML6 [9]進行解析:

EdgeHTML分兩個階段來處理標記,從CHtmPre::Exec()或CXmlPre::Exec()開始的預解析階段涉及到標記的初始解析、將解析的標簽寫入標簽流以及開始下載引用資源(如果可用 - 比如圖像和CSS文件),從CHtmPost::Exec()開始的后解析階段則從標簽流中獲取標簽,如果需要可對標簽執行進一步解析,并最終創建DOM對象。

而通過調用xmllite!CreateXmlReader()函數實例化的IXmlReader接口會被CXmlPre作為解析器用于預解析基于XML的標記,同時,當檢測到XML文件中有引用XSL樣式表時,此接口也會被CBaseXSLTFilter用作XML解析。另外,MSXML6的IXMLDOMDocument接口會被CBaseXSLTFilter用于轉換引用了XSL樣式表的XML文件。

引擎中一個重要的變化是對于二進制行為的支持[10],包括刪除內置的VML。基于VML的(VGX.DLL)漏洞[11]是很嚴重的,因其雖然過時,但在IE11/MSHTML下仍然可以默認使用。

預計隨著時間的推移,渲染引擎對標記/樣式的處理,特別是CSS和HTML的解析會有所更新,因為屆時將會有新的Web標準需要新的HTML標簽、HTML屬性、CSS屬性等來支持。與此相關的一個較有名0day例子是MSHTML CSS遞歸導入漏洞[12]。

3.2 圖像的解碼

圖像渲染是EdgeHTML引擎的另一基本任務,其中圖像文件可通過鏈接或以HTML標簽(如<img><embed>標簽)的方式傳給引擎。

我們可以通過查看g_rgMimeInfoImg數組來枚舉所支持的圖像格式,此數組包含指定圖像MIME類型的MIMEINFO項以及用于實例化相關圖像處理接口的函數。

如下是EdgeHTML支持的圖像格式,從Library列可以看出所有的圖像都是通過Windows Imaging Component (WIC)[13]進行處理的(SVG格式則通過3.1小節中描述的標記來處理):

對于圖像的處理,EdgeHTML首先通過CWicGlobals::GetWicImagingFactory()函數實例化WIC的IWICImagingFactory接口,接著再調用IWICImagingFactory::CreateDecoder()函數來為特定的圖像格式實例化一個IWICBitmapDecoder接口。

一個有意思的變化是EdgeHTML中對WMF和EMF圖像格式的支持被刪除了,意味著先前借助GDI庫來解析遠程WMF和EMF文件的依賴也被移除了,與此相關的遠程利用漏洞已經是屢見不鮮了[14,15,16]。

3.3 音頻/視頻的解碼

通過鏈接或HTML的<audio><video>標簽,我們可將任意音頻/視頻內容交由渲染引擎處理,所支持的音頻/視頻格式的Mime信息可在g_rgMimeInfoAudiog_rgMimeInfoVideo數組中得到。此外,正如下表所示,EdgeHTML中用于處理音頻/視頻內容的依賴庫是Media Foundation(MF)[17]:

EdgeHTML引擎會借助MFCreateMediaEngine()函數來實例化MF的IMFMediaEngine接口,以此設定媒體源并對播放進行控制。

除了音頻/視頻文件外,EdgeHTML引擎還會處理計時文本軌道[18],我們可通過HTML的<track>標簽來指定,引擎中支持的兩種文本軌道文件格式如下:

其中,TTML是基于XML的,處理它的EdgeHTML類會借助XmlLite的IXmlReader接口進行解析。

3.4 字體渲染

任意字體都可通過CSS @font-face 規則傳給EdgeHTML渲染引擎[19]。而對于字體解析漏洞[20],特別的,如果能通過瀏覽器渲染引擎觸發的話,那么就可能造成遠程利用 - CVE-2011-3402 [21,22]就是這樣一個例子,它為GDI中的字體解析漏洞(位于Win32k.sys模塊),此漏洞最初被用于0day攻擊,后來被集成到瀏覽器的漏洞利用套件中。

EdgeHTML引擎使用DirectWrite [23]來渲染字體且支持的格式如下:

所需DirectWrite接口的實例化是由CDXResourceDomain::EnsureDXFactories()函數完成的,且引擎會通過CDXEmbeddedFontFace::Initialize()函數檢測實際的字體格式,并通過IDWriteFactory::CreateCustomFontFileReference()調用在CDXPrivateFont::Initialize()函數中執行自定義字體的注冊。

與GDI不同,DirectWrite(DWrite.dll)由其所在的用戶態進程來解析字體文件。另外,EdgeHTML引擎中一個顯著的變化是EOT字體格式的支持被刪除了,這意味著解析EOT字體的T2EMBED [24]和GDI依賴也被刪除了,因此用于解析字體的函數庫就相應減少了。

3.5 DOM API

DOM (Document Object Model) API [25]是渲染引擎中最大的攻擊面之一。當解析HTML文檔時,渲染引擎會實例化那些用于表示HTML標簽的DOM對象,同時引擎還將創建諸如document這樣的核心對象,且新的DOM對象還可通過JavaScript代碼來動態實例化,我們這里討論的DOM API則提供了一種操作這些對象的方法。

當DOM對象的屬性被更改或其方法經由腳本被調用時,渲染引擎中會執行相應的代碼:

因DOM API調用而執行的渲染引擎代碼可改變DOM樹、DOM對象和渲染引擎內部對象,其中,非可預期的輸入、非可預期的狀態改變以及錯誤的內部狀態都可能導致產生諸如釋放后重用[26](例子如下)、堆溢出[27]、無效指針訪問[28]等內存錯誤漏洞。

借助2.2小結所述的比對方法,我們可在CFastDOM命名空間下找到EdgeHTML引擎中那些新增的DOM對象類型:

+CFastDOM::CAnalyserNode
+CFastDOM::CAriaRequestEvent
+CFastDOM::CAudioBuffer
+CFastDOM::CAudioBufferSourceNode
+CFastDOM::CAudioContext
+CFastDOM::CAudioDestinationNode
+CFastDOM::CAudioListener
+CFastDOM::CAudioNode
+CFastDOM::CAudioParam
+CFastDOM::CAudioProcessingEvent
+CFastDOM::CBiquadFilterNode
+CFastDOM::CClipboardEvent
+CFastDOM::CCommandEvent
+CFastDOM::CConvolverNode
+CFastDOM::CCryptoKey
+CFastDOM::CCryptoKeyPair
+CFastDOM::CCSS
+CFastDOM::CCSSConditionRule
+CFastDOM::CCSSGroupingRule
+CFastDOM::CDataCue
+CFastDOM::CDataTransferItem
+CFastDOM::CDataTransferItemList
+CFastDOM::CDeferredPermissionRequest
+CFastDOM::CDelayNode
+CFastDOM::CDynamicsCompressorNode
+CFastDOM::CEventTarget
+CFastDOM::CGainNode
+CFastDOM::CGamepad
+CFastDOM::CGamepadButton
+CFastDOM::CGamepadEvent
+CFastDOM::CHashChangeEvent
+CFastDOM::CIsolatedGlobalScope
+CFastDOM::CMediaDeviceInfo
+CFastDOM::CMediaDevices
+CFastDOM::CMediaStream
+CFastDOM::CMediaStreamError
+CFastDOM::CMediaStreamErrorEvent
+CFastDOM::CMediaStreamTrack
+CFastDOM::CMediaStreamTrackEvent
+CFastDOM::CMSAppAsyncOperation
+CFastDOM::CMSHeaderFooter
+CFastDOM::CMSPrintManagerTemplatePrinter
+CFastDOM::CMSTemplatePrinter
+CFastDOM::CMSWebViewSettings
+CFastDOM::CNavigationEventWithReferrer
+CFastDOM::COfflineAudioCompletionEvent
+CFastDOM::COfflineAudioContext
+CFastDOM::COscillatorNode
+CFastDOM::COverflowEvent
+CFastDOM::CPannerNode
+CFastDOM::CPermissionRequest
+CFastDOM::CPermissionRequestedEvent
+CFastDOM::CRTCDtlsTransport
+CFastDOM::CRTCDtlsTransportStateChangedEvent
+CFastDOM::CRTCDtmfSender
+CFastDOM::CRTCDTMFToneChangeEvent
+CFastDOM::CRTCIceCandidatePairChangedEvent
+CFastDOM::CRTCIceGatherer
+CFastDOM::CRTCIceGathererEvent
+CFastDOM::CRTCIceTransport
+CFastDOM::CRTCIceTransportStateChangedEvent
+CFastDOM::CRTCRtpListener
+CFastDOM::CRTCRtpReceiver
+CFastDOM::CRTCRtpSender
+CFastDOM::CRTCRtpUnhandledEvent
+CFastDOM::CRTCSrtpSdesTransport
+CFastDOM::CRTCSsrcConflictEvent
+CFastDOM::CScriptProcessorNode
+CFastDOM::CServiceUIFrameContext
+CFastDOM::CStereoPannerNode
+CFastDOM::CSVGForeignObjectElement
+CFastDOM::CVideoTrack
+CFastDOM::CVideoTrackList
+CFastDOM::CWaveShaperNode
+CFastDOM::CXMLHttpRequestUpload
+CFastDOM::CXPathEvaluator
+CFastDOM::CXPathExpression
+CFastDOM::CXPathNSResolver
+CFastDOM::CXPathResult
+CFastDOM::CXSLTProcessor

這些新增DOM對象類型表示EdgeHTML中新引入了的代碼或代碼路徑,它們可通過DOM API來訪問。

就枚舉DOM對象的屬性和方法而言,我們可以借助JavaScript的for...in語句。下述例子用到了新的XSLTProcessor DOM對象類型:

而通過比較DOM對象屬性的枚舉結果,我們可以得出那些已存在的DOM對象類型其屬性的變化情況。以下是document對象的屬性比對片段,至于新增DOM對象類型也是相似的:

 […]
+document.evaluate
 document.execCommand
 document.execCommandShowHelp
+document.exitFullscreen
 document.fgColor
-document.fileCreatedDate
 […]

此外,我們還可通過IDA中名稱窗口的查詢來確認DOM對象的屬性和方法:

通過跟蹤名稱窗口中列出的其中一個函數,我們最終可以找到表示DOM對象類型的實際EdgeHTML類:

伴隨著新的特性被添加到Edge瀏覽器中[29],相對應的可能會引入新的DOM對象類型,或者將新的屬性/方法添加到已存在的DOM對象中,以此將這些新功能提供給開發人員。這些新的DOM對象類型、屬性和方法反過來也會成為新的被攻擊代碼,從而增大了渲染引擎的攻擊面。

3.6 FLASH和PDF渲染器

雖然從技術層面上講它們并不屬于渲染引擎的一部分且它們自身各有一組復雜的解析及渲染操作,但Windows的內置PDF渲染器[30](自Windows 8.1以來)和預安裝的Adobe Flash Player(自Windows 8以來)仍可被認為是EdgeHTML引擎用于渲染各種文件格式的眾多依賴之一,它們都是預安裝的[3],且默認情況下均可被EdgeHTML渲染引擎實例化:

其中,PDF渲染器是由CPDFHelper::LoadPdfDoc()函數實例化的,而Flash渲染器的實例化則是從CCodeLoad::BindToObject()函數開始的。

從攻擊者的角度看,能額外借助復雜的渲染器必然會有下述優勢:(1)這些復雜的渲染器都有一組可被利用的攻擊面及對應漏洞;(2)它們的某些特性可被用來繞過漏洞的利用防護 - 一個例子是利用Flash的JIT生成代碼繞過CFG保護 [31],另一個例子是0day利用中借助Flash Vector對象的corruption技術[32]繞過ASLR保護,此例由IE渲染引擎漏洞來實現內存Flash Vector對象的corruption[33]。雖然對通過Flash的JIT繞過CFG保護以及借助Flash的Vector對象繞過ASLR保護已有相關的防護措施(見4.3小節和[34]),但這兩個例子很好的闡述了如何借助程序的功能來實現利用。

3.7 分析與總結:漏洞利用攻擊面

在圖像和字體渲染方面,EdgeHTML引擎的攻擊面是在減少的,因為它不再支持EMF和WMF格式的圖像以及EOT字體,處理這些格式的依賴庫代碼(GDI和T2EMBED)中含有遠程利用漏洞也是小有歷史了。此外,刪除VML的支持(二進制行為)也有助于進一步減少EdgeHTML引擎的攻擊面。

然而,同其它現代瀏覽器一樣,這之中又引入了新的特性,而這些新功能則通過新的DOM對象類型/屬性/方法以及新的標記/樣式規范來實現。就EdgeHTML引擎而言,我們在DOM API中發現了新的攻擊維度,包括新的DOM對象類型以及已有DOM對象類型中新添加的屬性和方法。

此外,下述依賴庫在EdgeHTML引擎中是有用到的:

  • 用于XML解析的XmlLite
  • 用于XML轉換的MSXML6
  • 用于圖像解碼的WIC(Windows Imaging Component)
  • 用于音頻/視頻解碼的MF(Media Foundation)
  • 用于字體渲染的DirectWrite
  • 用于PDF渲染的內置WinRT PDF渲染器
  • 用于Flash渲染的預安裝Adobe Flash Player程序

通過分析這些庫的使用,我們進一步認識到了它們的重要性,畢竟我們現在對渲染引擎如何使用它們以及攻擊者如何能通過惡意輸入來遠程訪問這些代碼有了更多的理解。

4 漏洞利用防護措施

既然我們對引擎的攻擊面已經有了解了,那下面就來看看攻擊者為了成功在EdgeHTML或其任何依賴中實現利用都需要繞過哪些漏洞利用防護,此外,我們還會討論和提及那些由安全人員發現的已知防護措施繞過方法或防護中的薄弱點。

本節對EdgeHTML模塊所在的內容處理單元中涉及的緩解方案僅作簡要介紹,而把詳細的討論放在EdgeHTML引擎及其依賴的利用防護上。至于Windows堆相關的防護已經在各種論文或報告[35,36,37,38,39,40]中有詳細討論,這里就不再贅述了。

4.1 64位、ASLR、DEP和APPCONTAINER保護

在Win10 64位系統中,EdgeHTML渲染引擎模塊(%System32%\edgehtml.dll)所在的內容處理單元(MicrosoftEdgeCP.exe)默認運行在64位,且啟用了ASLR保護(HEASLR,ForceASLR)和DEP保護,并通過AppContainer來實現沙箱功能:

Edge內容處理單元的防護措施與Windows 8中Immersive版的IE相同,但與Windows 10,Windows 8(Desktop版的IE)和Windows 7上的IE11不同。

下表給出了不同Windows版本上Edge和IE內容處理單元所默認用到的保護措施:

其中,64位技術有助于緩解傳統的堆噴利用,該利用會將攻擊者可控的數據在堆上進行噴射,從而把數據布局到特定的地址處。當然,根據漏洞的不同,“相對堆噴”[28,41]也是可能的,例如漏洞包含一個有效堆指針,但指針在計算時被加上了一個攻擊者可控的或錯誤的數值。

同時,內容處理單元中還啟用了高熵ASLR保護(HEASLR)以及強制ASLR保護(ForceASLR)[42,43],其中,HEASLR保護給可重定位的內存區域增加了額外的信息熵,而ForceASLR保護能夠避免將不支持ASLR保護的DLL模塊加載到固定的內存地址。在啟用ForceASLR保護的進程中,繞過ASLR保護一般需要利用那些可預測內存地址的對象指針或使用漏洞來實現內存信息泄露,由于微軟目前正積極地解決前者[44,42],因此越來越多的攻擊將會依靠漏洞進行信息泄露[45,32]。

此外,AppContainer則是Windows 8中新引入的進程隔離機制,它被用在IE的增強型保護模式[46]沙箱中,可限制進程的讀/寫訪問權限和相關功能。目前,有幾種方法能夠繞過AppContainer沙箱保護(以及其它沙箱保護),這些方法包括了利用內核漏洞[47,48]、利用中級或更高權限進程中的漏洞[46,49,50]以及利用可寫資源[49]。

4.2 棧緩沖區安全檢查(/GS)

基于棧的緩沖區溢出通常被用于控制程序的執行流程,為了檢測此類利用,EdgeHTML引擎及其依賴均采用緩沖區安全檢查(/GS) [51]選項進行編譯。該檢測機制會在保存局部變量的緩沖區后面設置一個安全cookie,然后在函數返回前檢查此安全cookie,以確保返回地址和保存的寄存器沒有被緩沖區溢出所覆蓋。另外,該機制還對數據進行了備份,相關參數和局部變量的副本被存儲在緩沖區之前,以防止它們在緩沖區溢出的情況下被破壞:

該緩解措施已在各種論文[52,53]中進行了深入討論,并且相關機制還在不斷地更新[42],以期提高防護的覆蓋面。當然,此機制的一個局限是它并未考慮攻擊者能夠控制特定位置寫入數據的情況[54,20](例如可控的緩沖區索引/指針),這允許攻擊者直接越過安全cookie進行寫入。

4.3 執行流保護(CFG)

EdgeHTML引擎及其依賴中引入了新的漏洞利用防護措施,即CFG保護(Control Flow Guard)[55,56]。當啟用CFG保護時,編譯器將在程序中添加額外的檢測代碼,以確保間接調用的目的地址是有效的。此策略主要用于檢測并阻止異常的執行流程,比如通過設置執行地址的方式將流程重定向到ROP鏈中。

此防護機制的內部原理已被深入研究過了,相關內容發表于各種論文/報告中[57,58]。針對CFG保護的繞過[31],一種方法是借助Flash的JIT生成代碼,因為它是動態解析的,固其內部的間接調用不會被CFG保護覆蓋到。然而,這種繞過技術現在已通過Flash中額外引入的代碼得到了防護,只要生成調用指令,那么相應的就會通過ntdll!LdrpValidateUserCallTarget()函數進行檢查。此外,其它繞過CFG保護的思路還包括跳轉到有效的API地址(如LoadLibrary)[41]、覆蓋堆棧數據(如返回地址)[57,41]等。

4.4 虛表保護(VTGUARD)

VTGuard(Virtual Table Guard)[42]是EdgeHTML中的另一漏洞利用防護措施,但此機制并沒有被應用到相關依賴中。VTGuard是在IE10中首次引入的,其目的在于檢測虛函數表是否有效,主要針對通過內存中可控的C++對象來控制程序執行流的利用情形,它在虛函數表中添加了一個__vtguard隨機值,執行虛函數調用前將對該值進行檢查:

此防護的一個缺點是它僅適用于EdgeHTML中的類對象,并且如果能通過內存信息泄露獲取__vtguard的地址,那么就可以簡單地進行繞過。

4.5 內存垃圾回收(MEMGC)

Memory GC(MemGC)[59]是在Win10的EdgeHTML和MSHTML渲染引擎中首次引入的,它衍生于早期的Memory Protector [60, 61, 62]漏洞利用防護。

與Memory Protector一樣,MemGC的目的是通過阻止內存塊(chunk)的釋放(如果還能找到相關的引用)來緩解UAF(use-after-free)漏洞[26]的利用。但是,與Memory Protector只檢查寄存器以及堆棧中的內存塊(chunk)引用不同,MemGC還會掃描托管堆中的內容來查找引用,這種附加檢查意味著它能進一步減少攻擊者可利用的UAF漏洞。

配置

MemGC是默認啟用的,在Edge和IE中都可通過“OverrideMemoryProtectionSetting”屬性進行配置,相應的注冊表項如下:

HKEY_CURRENT_USER\SOFTWARE\Microsoft\Internet Explorer\Main
OverrideMemoryProtectionSetting = %DwordValue%

其中,%DwordValue%可取下述任意值:

MEMGC堆管理

MemGC使用單獨的托管堆(MemGC堆)進行對象空間的分配,且通過并發的垃圾回收機制執行標記和清除操作,以此識別和回收堆中未被引用的內存塊(chunk),這個過程中MemGC會依賴Chakra(JavaScript引擎)的內存管理代碼來實現大部分功能。

在用到的分配方案中,MemGC首先會通過VirtualAlloc()函數申請大量被稱為Segment的內存空間,接著將這些Segment按4096字節劃分為Page頁面,而后再將其中的一組Page作為一個Block塊,在此基礎上按照相似大小原則進行對象空間的分配:

其中,EdgeHTML/MSHTML DOM對象以及大量的渲染引擎內部對象都是由MemGC管理的,此外,由于MemGC中已經使用了單獨的托管堆,所以如果它是啟用的,那么將不會再用到隔離堆。

分配

在EdgeHTML引擎的MemGC實現中,當需要分配一個托管對象時,edgehtml!MemoryProtection::HeapAlloc<1>()或edgehtml!MemoryProtection::HeapAllocClear<1>()函數將被調用,并轉而通過chakra!MemProtectHeapRootAlloc()函數進行處理。而chakra!MemProtectHeapRootAlloc()函數首先會尋找合適的bucket,然后從指向的Block中為其分配一個相應的chunk,最后將此chunk標識為root。在垃圾回收中,root標識表示該對象/chunk在程序中存在直接引用,因此不能被回收,同時,在搜索chunk引用時也會掃描這些標識為root的對象/chunk。

釋放

當對象需要被釋放時,引擎將會調用edgehtml!MemoryProtection::HeapFree()函數進行處理并轉而執行chakra!MemProtectHeapUnrootAndZero()調用。對于chakra!MemProtectHeapUnrootAndZero()函數,它將定位此chunk所在的具體Block,并將chunk的內容清零,然后去除它的root標識。通過清除root標識,此chunk成了潛在的回收目標,如果回收器未找到關于此chunk的相關引用,那么它就會被回收。

垃圾回收

一旦未被root標識的chunk總大小達到特定閾值,那么就會由chakra!MemProtectHeap::Collect()函數觸發垃圾回收機制。垃圾回收過程(因其復雜性,這里僅描述相關的核心功能)將通過標記和清除操作來回收那些未被引用的且未被root標識的chunk,其中的部分操作將在chakra!Memory::Recycler::StartConcurrent()函數下發的獨立線程(chakra!Memory::Recycler::ThreadProc)中進行。

在標記階段,首先會清空所有的chunk標記位,然后標記所有root標識的chunk(通過chakra!Memory::Recycler::BackgroundResetMarks()函數),接著掃描root標識的chunk(通過chakra!Memory::Recycler::ScanImplicitRoots()函數)、寄存器以及堆棧(通過chakra!MemProtectHeap::FindRoots()函數)來搜索chunk指針,并將找到的那些存在引用的chunk進行標記。最終,當標記階段完成后,那些仍未被標記的chunk將可重新用于對象的分配。

在撰寫本文時,所涉案例中尚無已知的有關MemGC和Memory Protector的繞過手法,但與其它利用防護一樣,將來可能也會出現相關的繞過技術。另一方面,目前公開的有借助Memory Protector實現32位IE中ASLR保護繞過的技術,以及借助Memory Protector實現的64位IE上用于近似分配過程中(包括堆分配)地址區間的時序攻擊,當然,這里給出的例子并不是針對Memory Protector的繞過。

4.6 分析與總結:漏洞利用防護措施

默認配置下,與Windows 10、Windows 8(Desktop版的IE)以及Windows 7上運行的IE11內容處理單元相比,EdgeHTML引擎所在的內容處理單元中涉及的漏洞利用防護措施要更加全面 - 它默認運行在64位,從而允許ASLR保護工作于HEASLR模式,這導致了傳統的堆噴技術變得不再可行或非常不可靠,因此,為了實現可控數據的內存布局,攻擊者必然要開發出更為精確的利用技術。

另一主要區別是,Egde中采用了約束性更強的AppContainer來實現沙箱的功能,這極大限制了引擎中利用程序的訪問權限和相應功能,所以除非此漏洞還存在于特權進程或系統組件[20]中,否則就需要借助另外的漏洞進行AppContainer沙箱逃逸。

同時,棧緩沖區安全檢查(/GS)能減少潛在的可利用堆棧漏洞,而要繞過執行流保護則需要借助于新的利用技術,并且同Memory Protector一樣,MemGC將會進一步減少引擎中可利用的UAF漏洞。

總體來說,依托于這些防護手段,攻擊者要想在EdgeHTML引擎中發掘可利用的漏洞則需要更多的投入,若需開發可靠利用則尤甚。言雖此,但攻擊者勢必會不斷尋找新的方法來繞過這些保護,可以預見的是防護措施也將隨著時間的推移而逐漸演變。

5 結論

EdgeHTML渲染引擎(以及其它瀏覽器渲染引擎)的攻擊面將不可避免地隨著Web新標準的實行而不斷增多,其中的大部分將會來自對新標記/樣式的解析,最明顯的莫過于那些經由DOM API導出給開發人員(當然還有攻擊者)的新功能。

另一方面,引擎中新增的攻擊面會通過應用于內容處理單元、相關依賴庫以及其自身模塊中全面的利用防護來進行緩解,這些防護措施將使許多引擎漏洞變得不可利用或者開發利用程序的難度變得非常大。

此外,下述與EdgeHTML引擎相關的研究領域不僅重要且很有意思,涉及內容都是可被遠程訪問且廣泛用到的庫/特性:

  • 引擎中所用Windows組件的原理研究、代碼審計以及Fuzzing:XmlLite、MSXML6、Windows Imaging Component(WIC)、Media Foundation(MF)、DirectWrite和WinRT PDF Renderer。其中一些可能已經有公開成果了(比如DirectWrite [20]),但是還需要更多有關的研究,這樣我們才能對此類關鍵組件的安全性有所了解。

  • 內部實現(算法細節,數據結構等)、Heap Grooming、堆元數據攻擊(如果可能)以及對MemGC繞過技術的研究。本文對MemGC進行了初步的探討,此外,針對其內部原理的進一步分析、研究如何通過MemGC堆進行攻擊利用以及研究如何繞過MemGC保護將有助于理解其防護中的薄弱點,從而實現對它的改進。

最后,衷心希望本文能對你理解EdgeHTML渲染引擎安全性方面的知識起到幫助:P

*注:參考文獻的信息詳見原文


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