前言 在前一部分中,我們介紹了從IE6到IE11的堆噴射方法,其實(shí)堆噴射只是一種手段目的還是為了實(shí)現(xiàn)最后的漏洞利用。在這一篇文章中,我們會根據(jù)時(shí)間順序來講解IE瀏覽器漏洞利用技術(shù)的發(fā)展,我們會把主要精力放在UAF漏洞的利用上面,同時(shí)會涉及一些其它類型的漏洞作為輔助以繞過漏洞緩解措施,這篇文章主要介紹技術(shù)發(fā)展脈絡(luò),實(shí)際的漏洞調(diào)試會放在下一章,期間我閱讀了大量的文檔、會議PPT和博客文章,在此也對前輩們的分享表示感謝。同時(shí)給大家分享兩句我很喜歡的話,一句來自大家應(yīng)該都很熟悉的陳皓大牛,一句來自charles petzold大家應(yīng)該都有讀過他的書 要了解技術(shù)就一定需要了解技術(shù)的歷史發(fā)展和進(jìn)化路線。因?yàn)?,你要朝著球運(yùn)動的軌跡去,而不是朝著球的位置去,要知道球的運(yùn)動軌跡,你就需要知道它歷史上是怎么跑的。 學(xué)習(xí)技術(shù)發(fā)展史的重要意義正在于此:追溯的歷史越久遠(yuǎn),技術(shù)的脈絡(luò)就變得越清晰。因此,我們需要做的就是確定某些關(guān)鍵的歷史階段,在這些階段,技術(shù)最天然、最本質(zhì)的一面將清晰可見。 首先簡單介紹一下本篇文章將要提到的漏洞類型,我們這篇文章主要會針對兩類漏洞進(jìn)行描述,即越界訪問漏洞和釋放后重引用漏洞。這兩種漏洞的英文名稱分別為Out-of-Bound和Use-After-Free,因此我們通常簡稱這類漏洞為OOB和UAF。 1.越界訪問漏洞 越界訪問漏洞,個(gè)人認(rèn)為越界訪問漏洞應(yīng)該是按照漏洞造成的效果進(jìn)行劃分的,而不是依照漏洞成因進(jìn)行的劃分。我認(rèn)為如果是從成因的分類上來講,像堆溢出、整數(shù)溢出、類型混淆等都可以造成越界訪問漏洞。 越界訪問,所謂的訪問就是指越界讀和越界寫,在后面我們可以看出越界漏洞是比較容易利用,也是比較好用的一類漏洞,這里好用指的是效果比較好,一般通過這種OOB漏洞可以在IE瀏覽器中輕易的實(shí)現(xiàn)繞過ASLR的保護(hù)。 而這種漏洞的利用,一個(gè)共通點(diǎn)是要進(jìn)行內(nèi)存布局(或稱為Feng shui技術(shù))。即把一些特殊的對象或者結(jié)構(gòu)布置在漏洞對象附近,否則讀寫都無從談起,我們會在后面展開來說這些內(nèi)容。 2.釋放重引用漏洞 Use-After-Free漏洞中文名為釋放后重引用漏洞,這種漏洞估計(jì)大家都比較熟悉。 所謂的“釋放重引用”是指在一塊內(nèi)存被釋放后在某處還保存有指向這塊內(nèi)存的懸垂指針,之后對懸垂指針進(jìn)行了解引用(所謂的重引用)導(dǎo)致了漏洞的觸發(fā)。 我們分析UAF漏洞一般要搞清楚幾個(gè)關(guān)鍵點(diǎn): 1.是什么對象發(fā)生的UAF? 2.UAF對象何時(shí)被分配、何時(shí)被釋放? 3.導(dǎo)致crash的流程是什么? 4.為什么會存在懸垂指針? 但是在早期的UAF漏洞利用來說,一些Hacker們往往只需要知道步驟2、3就可以實(shí)現(xiàn)漏洞利用。這是因?yàn)樵缙诘腢AF一般都是通過占位和堆噴射來進(jìn)行利用的,比較簡單粗暴。 1.為什么IE中會存在大量的Use-After-Free漏洞? 我們的第一個(gè)問題是IE瀏覽器中為什么會爆出大量的UAF漏洞? 這個(gè)問題的提出并不奇怪,因?yàn)槠渌能浖T如Office Word的漏洞可能基本上都是一些堆棧溢出,而UAF則是鳳毛麟角。 IE瀏覽器中并不是沒有存在過棧溢出這些類型的漏洞,而是經(jīng)過了十余年的發(fā)展基本都已消耗絕跡,但是UAF漏洞“絡(luò)繹不絕”的本質(zhì)原因在于IE瀏覽器中存在著大量的各種類型的對象和其間互相關(guān)聯(lián)的關(guān)系,包括各種標(biāo)簽和各種內(nèi)部數(shù)據(jù)結(jié)構(gòu)比如CElement就是代表元素對象的父類,舉例來看CButton是CElement的子類代表<Button>標(biāo)簽。 這些html標(biāo)簽和DOM Tree是由IE瀏覽器中的渲染引擎mshtml(就是所謂的Trident)負(fù)責(zé)解析的。html標(biāo)簽在mshtml內(nèi)部就是由一個(gè)個(gè)的C++對象來進(jìn)行表示的,同樣DOM樹也是通過一些數(shù)據(jù)結(jié)構(gòu)來進(jìn)行描述(比如CTreeNode、CTreePos),這些對象之間存在復(fù)雜的相互關(guān)系。并且mshtml使用了引用計(jì)數(shù)的方法來跟蹤對象的使用情況。 我們可以通過泄漏的IE5.5源代碼來觀察這一點(diǎn),雖然IE5.5版本對于我們來說已經(jīng)是相當(dāng)?shù)墓爬狭?,但是其?shí)一些核心的部分還是相當(dāng)相近的。 如下是IPrivateUnknown接口,這個(gè)接口在我們源碼中存在著如下的繼承關(guān)系CElement->CBase->IPrivateUnknown。 1 2 3 4 5 6 7 interface IPrivateUnknown { public: STDMETHOD(PrivateQueryInterface)(REFIID riid, void** ppv) = 0; STDMETHOD_(ULONG, PrivateAddRef)() = 0; STDMETHOD_(ULONG, PrivateRelease)() = 0; }; 在此我推薦閱讀以下兩篇文章,可以增進(jìn)對IE瀏覽器的了解: 《IE安全系列:IE瀏覽器的技術(shù)變遷(上)》 http://www./cn/articles/Internet-Explorer-Security1 《IE安全系列:IE瀏覽器的技術(shù)變遷(下)》 http://www./cn/articles/InternetExplorer-Security2 2.如何利用IE中的Use-After-Free漏洞 如何利用UAF漏洞是我們這篇文章的主題,在分門別類的進(jìn)行討論之前,我們首先介紹一些基礎(chǔ)知識。我們在前面介紹了UAF漏洞的一些信息,對于UAF漏洞的利用無論在什么時(shí)期,一個(gè)通用的步驟就是在UAF對象被釋放之后馬上去分配一個(gè)相同大小的內(nèi)存塊,我們稱這一步操作為“占位”。占位的原理在于堆分配的機(jī)制,當(dāng)一塊堆內(nèi)存被釋放后出于效率的考慮會被保存在一些結(jié)構(gòu)中以便于再次的分配。占位就是利用這一點(diǎn),通過分配相同大小的堆內(nèi)存試圖重用UAF對象的內(nèi)存,對Linux堆有了解或是打過CTF的同學(xué)應(yīng)該都比較熟悉這一點(diǎn)了。為了成功實(shí)現(xiàn)占位,一般是多次分配相同大小的內(nèi)存以保證成功率。 需要說明的一點(diǎn)是,不是所有的UAF漏洞都是可以利用的,因?yàn)橐恍┞┒礋o法進(jìn)行占位。比如有的漏洞它的對象釋放和重用操作就在同一個(gè)函數(shù)中,剛剛釋放完馬上就重用了,這種情況根本沒有機(jī)會去進(jìn)行占位,從而無法進(jìn)行利用。 我們說了這么久的占位,其實(shí)占位的目的是為了控制對象的內(nèi)容。同樣目的的操作,還有挖坑法(make hole),挖坑法是指在布局好的內(nèi)存中釋放一個(gè)指定大小的塊,好讓目的對象落在我們布局的內(nèi)存中,我們會在后文提到這一點(diǎn)。還有內(nèi)存未初始化漏洞的利用也與之類似,內(nèi)存未初始化漏洞是指分配一塊內(nèi)存后未經(jīng)初始化就直接進(jìn)行使用,我們?yōu)榱丝刂莆闯跏蓟瘜ο蟮膬?nèi)容會先釋放一些與之相同大小的已布置好內(nèi)容的內(nèi)存,然后讓未初始化對象來重用我們的內(nèi)存。 接下來我們就根據(jù)歷史發(fā)展來討論利用技術(shù),可以看出隨著歷史的向前漏洞利用技術(shù)有了很大的發(fā)展,相比早期的利用技術(shù)現(xiàn)在無論是在思路還是在手法上都是發(fā)生了質(zhì)的飛躍。 3.IE6漏洞利用(史前時(shí)代) 我們把IE6作為IE漏洞利用的開端,我們稱之為史前時(shí)代,說到史前我們可能會想到刀耕火種、茹毛飲血。此時(shí)的IE漏洞就是處于這樣一個(gè)野蠻生長的時(shí)代,漏洞利用技術(shù)簡單粗暴導(dǎo)致網(wǎng)馬大量橫行。主要原因在于IE6時(shí)代的瀏覽器版本不支持DEP等漏洞緩解措施(雖然此時(shí)操作系統(tǒng)已經(jīng)支持DEP),導(dǎo)致漏洞利用的成本低廉,但是也因此流傳下來一些“遠(yuǎn)古神話”,比如經(jīng)典的0x0C0C0C0C。 這一時(shí)期由于Active X插件作者的水平參差不齊,因此大量的控件存在有諸如棧溢出之類的簡單漏洞,利用方式也極為簡單粗暴配合堆噴就可以實(shí)現(xiàn)利用,這些漏洞我們簡單略過不再詳述。 我們把關(guān)注重點(diǎn)放到此時(shí)的UAF漏洞上面,通過我們前面對UAF漏洞的簡單介紹就可以看出,UAF漏洞與棧溢出有著本質(zhì)不同。棧溢出可以簡單直接的控制返回地址從而劫持執(zhí)行流程,但是UAF往往是處于堆上并沒有直接劫持流程的途徑。為了能夠在堆上劫持指令執(zhí)行流程,前輩們想出了劫持虛函數(shù)調(diào)用的方法。 我們首先簡單介紹一下虛函數(shù),在C++程序中,如果一個(gè)類存在虛函數(shù)那么當(dāng)這個(gè)類實(shí)例化對象后,對象的前4個(gè)字節(jié)就是虛函數(shù)表的指針,當(dāng)我們調(diào)用虛函數(shù)時(shí)實(shí)際上是到虛函數(shù)表中尋找函數(shù)指針。接下來,我們就通過這一點(diǎn)來進(jìn)行利用。 我們首先通過占位來控制UAF對象的內(nèi)容(如果你不理解這一步,可以往前看一看),控制了對象的內(nèi)容就相當(dāng)于控制了虛函數(shù)表的指針。接下來我們需要一個(gè)穩(wěn)定可達(dá)的地址,因此我們使用上一篇文章講過的堆噴射,然后把虛表指針指向我們噴射的內(nèi)存地址,這樣一旦觸發(fā)漏洞就會把我們的噴射內(nèi)存當(dāng)作虛表來執(zhí)行了。 為什么一觸發(fā)漏洞就會把噴射內(nèi)存當(dāng)作虛表來執(zhí)行呢?如果沒有調(diào)試過IE漏洞可能會提出這個(gè)問題,因?yàn)槲覀儗?shí)際去調(diào)試漏洞就會發(fā)現(xiàn)事實(shí)上UAF漏洞觸發(fā)后基本都會crash在虛函數(shù)調(diào)用處,如果你發(fā)現(xiàn)windbg停在一個(gè)莫名其妙的地方很可能是因?yàn)闆]有開啟頁堆,可以使用!gflags.exe -i +hpa進(jìn)行開啟,關(guān)于頁堆可以學(xué)習(xí)一下張銀奎老師的《軟件調(diào)試》。(此外新手可能會發(fā)現(xiàn)明明異常了卻沒有停下來,可能是沒開啟子進(jìn)程調(diào)試,主要是對于IE8以后這種多進(jìn)程瀏覽器來說。) 根據(jù)我們上面的描述可以看出,我們是在把噴射的內(nèi)存當(dāng)成虛表。但是當(dāng)我們調(diào)用虛函數(shù)時(shí),往往是下面這個(gè)樣子的: 1 2 mov eax,[ecx] call [eax+4] 這兩條指令意味著,噴射的內(nèi)存不僅會被當(dāng)成虛表還會被當(dāng)成指令來執(zhí)行。并且更糟糕的情況是:這里我們不能確定堆噴射的準(zhǔn)確分配地址,就是說我們不能確定堆表指針到底噴射在哪里。這時(shí)就對我們的噴射提出了要求,我們需要尋找一個(gè)既可當(dāng)作地址解釋又可以當(dāng)作無意義指令解釋的值。 在這種情況下“上古傳說"0x0C0C0C0C就誕生了,如果我們使用0x0C0C0C0C作為噴射的內(nèi)容的話,當(dāng)mov eax,[ecx]時(shí)就會取到0x0C0C0C0C作為指針來進(jìn)行跳轉(zhuǎn),call [eax+4]會把0x0C0C0C0C的0x4處偏移取出并call,當(dāng)然其結(jié)果依然為0x0C0C0C0C,這樣call 0x0C0C0C0C會執(zhí)行指令0x0C,而0x0C相當(dāng)于nop就會最終執(zhí)行到shellcode了。當(dāng)年有很多這樣的通用地址存在比如0x0D0D0D0D、0x06060606。 這種利用方式簡單粗暴卻又有效,因此我們稱為史前時(shí)代,就像TK教主說的一樣: 在當(dāng)年無 DEP 的環(huán)境下,幾乎完全不懂漏洞原理的人,知道去 Heap Spary 0x0C0C0C0C 就能搭積木一樣寫出 Exploit,而且還很通用。 當(dāng)然,對于不涉及虛表訪問的利用來說,使用0x0c0c0c0c是完全沒有意義的。不過這個(gè)地址已經(jīng)成為一個(gè)"上古神話"了,所以我們還是會經(jīng)??吹玫剿踔劣谝恍┌踩浖坏┌l(fā)現(xiàn)這個(gè)值就會報(bào)警。 4.IE8早期漏洞利用(石器時(shí)代) 前面我們說IE6時(shí)期是史前時(shí)期,因?yàn)槟菚r(shí)的漏洞利用簡單粗暴。相比于當(dāng)時(shí),IE8時(shí)代的利用技術(shù)向前走了一大步,不過因?yàn)榘踩w系的問題早期的IE8利用依然只能稱為是石器時(shí)代,還是相當(dāng)?shù)脑肌?/p> 自IE8開始,DEP和ASLR成為瀏覽器中默認(rèn)啟用的緩解措施,如何bypass ASLR和DEP成為了攻擊者首要面對的問題。我們簡單介紹一下DEP和ASLR,如果是熟悉Linux的同學(xué),那么Linux下的NX保護(hù)與DEP是很類似的,都是把一些非代碼段內(nèi)存設(shè)為不可執(zhí)行來阻止攻擊者運(yùn)行shellcode。在其它的軟件中bypass DEP通常使用ROP技術(shù),但是由于IE幾乎都是基于堆的漏洞不存在直接進(jìn)行ROP的條件所以并不能通過簡單的ROP實(shí)現(xiàn)bypass DEP。而ASLR會使得模塊裝載的地址變得不確定,對漏洞利用有一些了解的同學(xué)肯定知道Rop技術(shù)是依賴于一些rop gadgets來進(jìn)行不斷的跳轉(zhuǎn)利用的,ASLR的啟用會直接妨礙我們獲取rop gadgets。 不過對于早期的利用,ASLR并沒有對利用者造成太大的困擾。因?yàn)锳SLR早就在諸如Office Word之類的軟件中啟用了,Hacker們直接套用了在這些軟件中的做法即利用一些未開啟ASLR的模塊進(jìn)行利用。因?yàn)楫?dāng)時(shí)很多的模塊并不支持ASLR因此加載在固定基地址。這種方法也是比較簡單粗暴的而且通用性比較差,比如以前在IE中常用的Java6的msvcr71.dll,如果目標(biāo)并沒有安裝JRE或者版本不對利用都不能成功。 因?yàn)榇藭r(shí)仍然比較原始,所以我們稱之為石器時(shí)代。事實(shí)上,今天的應(yīng)用程序不支持ASLR的已經(jīng)非常少見了,想通過不支持ASLR的模塊來實(shí)現(xiàn)ROP已經(jīng)不大可能了。所以我們把完整的利用方法放到下一章中詳述。 5.IE8瀏覽器結(jié)合信息泄漏利用(鐵器時(shí)代) 據(jù)說人類跟動物的區(qū)別是人類會使用工具,那么這一時(shí)期利用技術(shù)的進(jìn)步堪比從石器進(jìn)化到鐵器。 這一時(shí)期的標(biāo)志事件是Peter Vreugdenhil在Pwn2Own2010中攻破IE8項(xiàng)目,這一過程中的技術(shù)手段對后來的利用技術(shù)發(fā)展有著重要的作用。Peter Vreugdenhil利用IE8的手段是把一個(gè)OOB漏洞與一個(gè)UAF漏洞相互結(jié)合,我們首先來說OOB漏洞。Peter Vreugdenhil通過內(nèi)存布局把BSTR布置在存在OOB的對象后面,目的是進(jìn)行信息泄漏,通過越界寫來改變BSTR的長度,實(shí)現(xiàn)了越界讀。 我們在前面說過BSTR不是簡單的Unicode字符串,BSTR的結(jié)構(gòu)由4字節(jié)的長度(size)域、2字節(jié)的結(jié)束符()加上Unicode字符串構(gòu)成。通過我們精心構(gòu)造內(nèi)存布局,使BSTR對象緊隨漏洞對象的后面。之后再在BSTR后面再放置目標(biāo)對象,這樣當(dāng)觸發(fā)漏洞對象發(fā)生越界訪問的時(shí)候就可以覆蓋掉BSTR結(jié)構(gòu)的size域。一旦我們把size域覆蓋為更大的數(shù)值,我們就能夠使得BSTR發(fā)生越界讀(因?yàn)锽STR只可讀不可寫)。然后通過js腳本讀取BSTR字符串,就能夠讀到BSTR之后的對象。我們的目的是獲取后面對象的虛表地址(首4個(gè)字節(jié))。如果你想了解的更詳細(xì)可以參見(http:///Pwn2Own-2010-Windows7-InternetExplorer8.pdf ) 為什么獲得虛表地址就可以bypass ASLR呢?因?yàn)閷τ贑++程序來說虛函數(shù)表是被編譯在全局?jǐn)?shù)據(jù)段的,就是說對于模塊的基地址的偏移是固定的。我們通過泄漏的虛函數(shù)表的地址減去偏移就可以知道對象所處的dll模塊的基地址,也就可以使用這個(gè)模塊中的gadgets了。 這種方法有兩個(gè)需要解決的問題:第一是如何構(gòu)造穩(wěn)定的內(nèi)存布局使我們上述的內(nèi)容得以實(shí)現(xiàn)。第二是當(dāng)我們覆蓋成功后,如何通過javascript腳本層面上的操作把值獲取到。其實(shí)我們后面要講到的方法都面臨著這兩個(gè)問題。 由于這種利用較為簡單,可以直接參考泉哥的著作《漏洞戰(zhàn)爭:軟件漏洞分析精要》里面第三章的CVE-2012-1876的利用分析,其使用的方法就是通過BSTR進(jìn)行泄漏,我們也會在下一篇中給出實(shí)際的漏洞調(diào)試。 單單繞過ASLR是無法實(shí)現(xiàn)漏洞利用的,因?yàn)镈EP的存在我們沒有辦法在堆上執(zhí)行指令。為此Hacker們想了很多辦法,其中我認(rèn)為最早實(shí)現(xiàn)成功利用的依然是Pwn2Own 2010上Peter Vreugdenhil使用的方法,雖然與我們這里講的不完全相同,但是我覺得是Peter Vreugdenhil方法的進(jìn)化版。我們忽略Peter Vreugdenhil的方法(感興趣的可以查看上面的連接),我們使用的手段是stack pivot,所謂stack pivot就是通過mov esp,eax、xchg esp eax等指令來實(shí)現(xiàn)把棧轉(zhuǎn)移到堆上,因?yàn)橐话愕腢AF漏洞觸發(fā)時(shí)我們都可以控制至少一個(gè)寄存器的值。通過把esp指向我們噴射的內(nèi)存,我們就可以把堆偽造成棧,從而像普通的棧溢出一樣進(jìn)行ROP,通過執(zhí)行ROP最終實(shí)現(xiàn)代碼執(zhí)行。 但是這一利用方法首先要確保的是我們要能夠精準(zhǔn)的計(jì)算堆噴射的地址,因?yàn)槎巡豢蓤?zhí)行所以我們不能再依賴于用于緩沖的nop指令了。好消息是我們在前一篇文章中已經(jīng)講過準(zhǔn)確計(jì)算的原理和實(shí)現(xiàn)了,這里再簡單復(fù)述一下。當(dāng)我們大量分配堆塊時(shí)可以發(fā)現(xiàn)地址的最低幾位是一直不變的,地址改變的熵只是固定的地址高位并且堆塊的分配相當(dāng)?shù)姆€(wěn)定。這樣如果我們使偏移都落在地址的高位,那么我們的指向就會是整塊進(jìn)行偏移,從而保證了每次指向的都是計(jì)算好的準(zhǔn)確的地址。 舉個(gè)例子:我們可以以每個(gè)塊為單位計(jì)算出ROP鏈第一條地址的偏移,然后其實(shí)我們可以想一下0x0C0C0C0C這個(gè)地址還有沒有用?在這種利用環(huán)境下,第一不需要跳板指令,第二我們跳轉(zhuǎn)目的地址是精確的,那么0x0C0C0C0C這種地址就根本沒有存在的價(jià)值了。我們要的就只是一個(gè)堆噴射可達(dá)的穩(wěn)定的地址。 無堆噴射,通過ANIMATECOLOR對象實(shí)現(xiàn)利用 這種方法不需要進(jìn)行堆噴射就可以實(shí)現(xiàn)利用,堆噴射其實(shí)并不能說是一種優(yōu)雅的利用方法,因?yàn)榉峙鋬?nèi)存需要一定的時(shí)間,而且如果目標(biāo)機(jī)器的配置較低的話可能會導(dǎo)致卡頓從而被目標(biāo)察覺。我之前在binvul上看到過一些所謂的“不彈不卡不噴射不風(fēng)水”的樣本其實(shí)指的就是這種技術(shù)。 ANIMATECOLOR是IE8版本起提供的一種對象,由于這種對象的特殊構(gòu)造所以可以不使用堆噴射來實(shí)現(xiàn)利用,我們在下一篇實(shí)際漏洞調(diào)試時(shí)再來進(jìn)行分析。 6.結(jié)合Flash的利用(中世紀(jì)) 到這里瀏覽器利用技術(shù)又是一個(gè)飛躍,結(jié)合flash利用雖然不能說特別優(yōu)雅(因?yàn)橐揽康谌?,但中世紀(jì)是文藝復(fù)興的先聲,可以說自此之后利用技術(shù)又進(jìn)入了一個(gè)發(fā)展的新巔峰。 這種利用技術(shù)不是來自于Pwn2Own也不是來自于某次會議的分享,相反,隨著時(shí)間的發(fā)展,在2013年網(wǎng)上流傳出了一些無需多漏洞結(jié)合使用,通過單一漏洞就可以bypass緩解措施+執(zhí)行代碼的exp樣本,這些exp樣本應(yīng)該是用于實(shí)際攻擊的武器。其主要特點(diǎn)是結(jié)合了flash進(jìn)行漏洞利用,這種利用技術(shù)最早應(yīng)該是由李海飛前輩在《Smashing the Heap with Vector:Advanced Exploitation Technique in Recent Flash Zero-day Attack》這文章中提出的(CVE-2013-0634)。 1 This is in fact a somehow new technique which leverages the custom heap management on Flash Player to gain highly-reliable exploitation bypassing both the ASLR and DEP. 就像李海飛前輩所說,這完全是一種新技術(shù)。并且這種新技術(shù)可以只憑借一個(gè)單一的漏洞實(shí)現(xiàn)bypass全部的緩解措施并且執(zhí)行最終的shellcode,這一點(diǎn)是以前的exploit所做不到的事情。 我們簡單的概括一下利用的方法,我們先忽略漏洞的細(xì)節(jié)簡單的認(rèn)為它是一個(gè)0x90個(gè)字節(jié)的堆塊發(fā)生的溢出。我們首先分配一系列0x90大小的Vector對象,對于儲存數(shù)字的Vector來說每個(gè)數(shù)字占8個(gè)字節(jié),16個(gè)數(shù)字加上16字節(jié)的固定結(jié)構(gòu)正好滿足0x90的大小。 我們在vector對象布置完成之后,通過代碼來釋放一些0x90大小的vector,再觸發(fā)漏洞。之后會分配具有溢出的0x90大小的堆塊,因?yàn)槌叽缗c我們之前釋放的vector尺寸相同,根據(jù)堆的特性漏洞堆塊會重用我們之前釋放的vector對象內(nèi)存。這一步操作稱為挖坑(make holes),挖坑的目的是為了使得漏洞堆塊處于vector對象的包圍之中。 下一步,我們只需要利用溢出就可以覆蓋掉相鄰vector對象的“Number_of_elements”域。 覆蓋的結(jié)果是使得相鄰的vector可以發(fā)生越界訪問,通過操作這個(gè)越界的vector我們又可以覆蓋下一個(gè)vector的“Number_of_elements”域,但這次我們可以直接把“Number_of_elements”域改的很大,從而實(shí)現(xiàn)了整個(gè)進(jìn)程地址空間的任意讀寫。 一旦實(shí)現(xiàn)了整個(gè)內(nèi)存空間的進(jìn)程讀寫,就可以做到bypass DEP和ASLR了。 如果說這次利用只是因?yàn)槁┒幢旧碛斜容^合適的尺寸便于布局、有直接的溢出便于覆蓋結(jié)構(gòu)。那么陳小波前輩發(fā)布的《ASLR Bypass Apocalypse in Recent Zero-Day Exploits》中就給出了一個(gè)通用的思路,其中提到了很重要的一點(diǎn)就是:如何把一個(gè)常規(guī)的UAF漏洞往我們上面說的Flash vector越界寫上面進(jìn)行轉(zhuǎn)化。對于這個(gè)問題作者提供了如下的思路:以CVE-2013-0634為例,這是一個(gè)在IE瀏覽器中常見的UAF漏洞,在利用這個(gè)漏洞時(shí)exp作者在代碼執(zhí)行路徑上發(fā)現(xiàn)了一條指令: 1 or dword ptr [esi+8],20000h 其中esi的值是我們可控的(來自UAF對象,可以通過占位進(jìn)行控制),作者把它指向布置好了的Vector對象的長度域,在執(zhí)行了or之后長度域會變大從而使得這個(gè)vector可以進(jìn)行越界操作。之后可以通過這個(gè)vector越界寫緊鄰的下一個(gè)vector的長度域從而實(shí)現(xiàn)了整個(gè)進(jìn)程地址空間的任意讀寫。此外還要解釋一下為什么可以知道Vector對象的長度域的地址, 之后的IE瀏覽器利用從基本思想上發(fā)生了轉(zhuǎn)變,攻擊者不再追求結(jié)合多個(gè)漏洞泄漏信息再進(jìn)行堆上ROP,而是繼承了flash vector的任意讀寫轉(zhuǎn)化思路,試圖從UAF轉(zhuǎn)化到任意地址讀寫,再通過任意地址讀寫來實(shí)現(xiàn)繞過緩解措施。 7.UAF轉(zhuǎn)化與Element Attribute(啟蒙時(shí)代) 之后漏洞利用進(jìn)入啟蒙時(shí)代,相比flash利用這一時(shí)期的優(yōu)點(diǎn)是不再依賴于flash模塊。這樣可以提高漏洞利用的成功率和降低成本,因?yàn)榇藭r(shí)一個(gè)漏洞就可以實(shí)現(xiàn)多個(gè)漏洞的利用效果并且在flash利用爆發(fā)后安全軟件對夾雜flash的頁面十分敏感,不依賴flash可以提高漏洞利用的成功率。 在《A BROWSER IS ONLY AS STRONG AS ITS WEAKEST BYTE》這篇文章中,作者以CVE-2013-3147為基礎(chǔ)詳細(xì)講解了如何從crash地點(diǎn)進(jìn)行分析來尋找一條合適的代碼路徑把UAF轉(zhuǎn)化成inc [address](絕對地址加),并且避開虛函數(shù)調(diào)用以免引發(fā)crash。簡單的概括就是查找crash附近的代碼流程,尋找有沒有寫原語,如果存在這樣的原語就想辦法滿足邏輯條件把執(zhí)行流程引導(dǎo)寫原語上去。 值得注意的是作者在利用這個(gè)任意地址加的過程中并沒有依靠flash vector,而是通過噴射Element Attribute來實(shí)現(xiàn)利用。首先簡單介紹一下Attribute是什么,如果你有看過HTML那么應(yīng)該知道一些標(biāo)簽是具有屬性的,比如每個(gè)標(biāo)簽都有id屬性用做唯一的標(biāo)識。對應(yīng)于底層實(shí)現(xiàn)來說,每個(gè)DOM元素對應(yīng)的CElement結(jié)構(gòu)中也會有指針指向Attribute Array,每個(gè)屬性占其中一項(xiàng)。那么Element Attribute是如何實(shí)現(xiàn)利用的呢? 首先我們忽略漏洞的細(xì)節(jié),只看漏洞導(dǎo)致的效果,經(jīng)過轉(zhuǎn)化操作這個(gè)UAF漏洞可以引導(dǎo)到如下的路徑上 而第二個(gè)DWORD的值為屬性名的哈希值,第三和第四個(gè)值為實(shí)際的屬性內(nèi)容,如果屬性內(nèi)容是諸如字符串這樣的值,那么它會是一個(gè)指針。 作者的核心思路是對第三個(gè)DWORD那個(gè)指針進(jìn)行加1操作,因?yàn)槭且宰止?jié)為單位進(jìn)行加1,所以實(shí)際的操作效果可能是指針偏移0x1、0x100、0x10000、0x1000000。在這種思路之下作者進(jìn)行了內(nèi)存布局,通過構(gòu)造相同大小的BSTR字符串和一個(gè)元素來使得它們彼此相鄰的分配(相同大小通過計(jì)算可以輕易的得到,而且也正是因?yàn)樗鼈兇笮∠嗤圆艜l(fā)生彼此相鄰的分配),在布局完成之后對指針進(jìn)行加1操作就可以讀出后面元素的內(nèi)容,在實(shí)際利用過程中布局要更加復(fù)雜一些不過原理是一致的。 實(shí)際利用過程中作者一次性創(chuàng)建了含有0x7FFE個(gè)屬性的元素,然后復(fù)制它直到大小為0x800000個(gè)字節(jié)。然后對這些元素進(jìn)行遍歷,每隔0x1000個(gè)屬性就把它的值設(shè)置為一個(gè)0x8A大小的字符串,這個(gè)設(shè)置會導(dǎo)致在內(nèi)存中分配0x8A字節(jié)的字符串,然后馬上創(chuàng)建一個(gè)body元素并添加9個(gè)默認(rèn)屬性(大小正好是0x8A)這樣就做到了BSTR和元素的緊鄰分配。接下來就像我們上面所說的對指針加1就能讀到body元素的內(nèi)容了。因?yàn)閎ody默認(rèn)屬性中包含一些域,通過讀取它就可以算出mshtml.dll的基地址。 然后作者在這個(gè)基礎(chǔ)上繼續(xù)進(jìn)行改進(jìn),因?yàn)樽髡哒J(rèn)為mshtml.dll的版本變化比較多對于利用不是很理想,而且現(xiàn)在我們做的還只是泄漏操作沒有實(shí)際的進(jìn)行執(zhí)行流劫持,而我們這一階段的主題就是只通過單個(gè)漏洞來實(shí)現(xiàn)完整的利用。作者為了實(shí)現(xiàn)流程控制對屬性表進(jìn)行了覆蓋操作,但是又會受到低碎片堆機(jī)制的限制,為此又要偽造堆頭結(jié)構(gòu)。可見這種利用方法還是比較麻煩的,但是對Element Attribute結(jié)構(gòu)的利用思路對后來的漏洞利用思路有很大的幫助。 之后在2014年,這個(gè)時(shí)候Ivan Fratric的《Exploiting Internet Explorer 11 64-bit on Windows 8.1 Preview》發(fā)布出來。這篇文章的意義在于,作者針對javascript array對象進(jìn)行了分析,然后對array對象進(jìn)行Feng shui布局并且通過它的capacity域?qū)崿F(xiàn)了利用。由于js引擎是根據(jù)capacity域?qū)?shù)組大小進(jìn)行判斷的,因此我們一旦篡改了capacity域就可以對數(shù)組進(jìn)行越界訪問。在下一階段的利用中,我們就會看到array object在漏洞利用中起到的作用。 此外在2015年的Pwn2Own上,360 vulcan團(tuán)隊(duì)就是通過Element Attribute對IE11瀏覽器進(jìn)行的利用。不過與我們這里的情形不同,vulcan利用的漏洞恰好就是在處理Element Attribute時(shí)出現(xiàn)的未初始化問題,由于與文章主題無關(guān)這里就不贅述了,不過相信讀完本文之后你就可以理解古河講的利用思路了,利用的詳情可以查看http://www./course/52149。 8.IE11與針對jscript9引擎的攻擊(近現(xiàn)代) CanSecWest2014上,ga1ois在議題《The Art of Leaks》中討論了幾個(gè)很關(guān)鍵的問題。 第一是自IE9以后引入的jscript9引擎——jscript9.dll使用與以前不同的custom heap,而且這個(gè)custom heap并沒有做任何的分配隨機(jī)化措施,這一點(diǎn)給我們進(jìn)行內(nèi)存布局提供了可能。 第二是從UAF轉(zhuǎn)化為任意地址讀寫的過程中可能因?yàn)樘摫碓L問而導(dǎo)致crash和如何避免發(fā)生這種crash。 在IE9之前的版本中,javascript是由javascript解析引擎——jscript.dll負(fù)責(zé)解析的,這個(gè)dll在分配內(nèi)存時(shí)使用的是系統(tǒng)的進(jìn)程堆。而在最新的javascript解析引擎——jscript9.dll中,在分配一些對象時(shí)引擎會使用custom heap,這個(gè)custom heap是由jscript9自己負(fù)責(zé)管理和維護(hù)的。并且這個(gè)custom heap在分配時(shí)沒有進(jìn)行隨機(jī)化處理,以至于攻擊者可以通過布局一些對象(所謂的feng shui技術(shù))來預(yù)估出對象所處的地址。 其中直到0xf000之前的都是我們的array object填充數(shù)據(jù),而自0xf000起是我們想要的目標(biāo)對象,這里以int32Array作為目標(biāo)對象的例子。 因?yàn)楹罄m(xù)我們還會涉及到int32Array這個(gè)對象,所以我們這里詳細(xì)的介紹一下。int32Array屬于Typed array的一種,根據(jù)MDN的介紹Typed array有以下幾種 我們知道javascript是一種腳本語言,是難以像C語言一樣表示一些底層數(shù)據(jù)類型的,Typed array的設(shè)計(jì)就是為了解決這個(gè)問題。我們雖然可以直接使用new來創(chuàng)建一個(gè)Typed array對象,諸如 其中Arraybuffer Data就是直接保存數(shù)據(jù)的區(qū)域,并且這塊內(nèi)存是分配在process Heap上的。 一旦可以預(yù)估出對象的地址那么就可以通過把UAF轉(zhuǎn)化為絕對地址寫去篡改Int32Array對象的長度域,來實(shí)現(xiàn)Arraybuffer Data的越界讀寫。因?yàn)锳rraybuffer Data是儲存在process Heap中的因此需要一個(gè)分配在process Heap上的對象來配合利用。這里作者使用的是LargeHeapBlock,因?yàn)檫@個(gè)對象處于process Heap中,并且恰好存在合適的域來實(shí)現(xiàn)任意地址讀寫。我們可以看出這種利用jscript9的方法明顯比之前的做法要更穩(wěn)定和易于操作。 至于UAF到讀寫的轉(zhuǎn)化,與我們前面提過的大體相同就是跟蹤漏洞觸發(fā)附近的執(zhí)行流程尋找有沒有合適的轉(zhuǎn)化原語(opcode)。在轉(zhuǎn)化過程中可能會導(dǎo)致crash的問題,成功利用寫入原語之后會發(fā)生虛函數(shù)調(diào)用,如果虛表被破壞的話虛函數(shù)調(diào)用就會導(dǎo)致crash。對此ga1ois給出了解決方案: 之后,在同年的Hitcon上exp-sky進(jìn)一步發(fā)展了這一技術(shù),代碼和文檔可以在作者github中找到(https://github.com/exp-sky)。與ga1ois的不同之處在于exp-sky沒有使用typed array進(jìn)行布局,而是將IntArray Object作為目標(biāo)對象進(jìn)行布局。這一操作的優(yōu)點(diǎn)在于IntArray全部都是基于custom heap進(jìn)行操作的,如果你還記得我們上面講的內(nèi)容的話,你應(yīng)該知道我們在對typed array進(jìn)行篡改操作后進(jìn)行越界編輯的是Arraybuffer Data,而這塊內(nèi)存是存放于process heap中的,這就意味著我們還要進(jìn)一步的對process heap進(jìn)行布局,而這種方法則完全沒有這個(gè)必要。 注意這兩個(gè)結(jié)構(gòu)都處于Custom Heap并且是分配在一起的。 因此噴射IntArray相比前面的方法要更方便也更容易控制,由于ArrayBuffer對象存在有保存當(dāng)前緩沖區(qū)大小的域(buffer_size),只要通過絕對地址寫改寫這個(gè)域?yàn)楹艽缶涂梢赞D(zhuǎn)化為任意內(nèi)存讀寫了,之后再修改相鄰塊的域這一點(diǎn)與前面的技術(shù)是相同的。 總體來說,這一時(shí)期的利用思路基本都在于噴射一些關(guān)鍵的對象,并結(jié)合各種feng shui技術(shù)(尤其是jscript9中的)進(jìn)行布局。然后試圖把UAF轉(zhuǎn)化為絕對地址寫,來寫我們噴射對象的關(guān)鍵域從而實(shí)現(xiàn)從UAF到任意地址讀寫的跨越。 一旦獲得了任意地址讀寫就相當(dāng)于可以讓攻擊者進(jìn)行隨意利用,這時(shí)各種漏洞緩解措施就不再能夠阻擋攻擊者的腳步了。 這里我使用了一張demi6od在《Smashing the Browser》議題中使用的圖,這張圖很好的說明了我們所講的思路。 后記 其實(shí)這一系列的文章,我在去年10月份的時(shí)候就已經(jīng)寫完了,但是一直在硬盤里放了近半年都沒有投出來。我主要是考慮到這系列文章涉及的話題太廣、內(nèi)容太多、歷史又太悠久,考慮到自己僅是個(gè)大二學(xué)生水平較低、接觸漏洞方面也不久,唯恐內(nèi)容中出現(xiàn)錯誤和紕漏。但是做了一番修改后我還是鼓起勇氣發(fā)出來了,希望大家能夠幫忙修正文章中錯誤和提出修改建議,可以通過微博私信給我 id:Ox9A82。 Reference 《The Art of Leaks – The Return of Heap Feng Shui》Gaois https:///slides/2014/The%20Art%20of%20Leaks%20‐%20read%20version% 20‐%20Yoyo.pdf 《IE 11 0day & Windows 8.1 Exploit》exp-sky 《Smashing the Browser》demi6od 《瀏覽器漏洞攻防對抗的藝術(shù)》仙果 http://bbs./thread-211277.htm 《Exploiting Internet Explorer11 64-bit on Windows 8.1 Preview》 http://ifsec./2013/11/exploiting-internet-explorer-11-64-bit.html 《ASLR BYPASS APOCALYPSE IN RECENT ZERO-DAY EXPLOITS》 https://www./blog/threat-research/2013/10/aslr-bypass-apocalypse-in-lately-zero-day-exploits.html 《A BROWSER IS ONLY AS STRONG AS ITS WEAKEST BYTE》 http://blog./2013/11/26/browser-weakest-byte/ 《A browser is only as strong as its weakest byte – Part 2》 https://blog./2013/12/09/a-browser-is-only-as-strong-as-its-weakest-byte-part-2/ 《Smashing the Heap with Vector:Advanced Exploitation Technique in Recent Flash Zero-day Attack》 https://sites.google.com/site/zerodayresearch/smashing_the_heap_with_vector_Li.pdf?attredirects=0 《IE安全系列:IE瀏覽器的技術(shù)變遷(上)》 http://www./cn/articles/Internet-Explorer-Security1 《IE安全系列:IE瀏覽器的技術(shù)變遷(下)》 http://www./cn/articles/InternetExplorer-Security2 《攻破Windows 8.1的64位IE - 分享Pwn2Own黑客大賽成果》 《Pwn2Own 2010 Windows 7 Internet Explorer 8 exploit》 http:///Pwn2Own-2010-Windows7-InternetExplorer8.pdf 《Flash Vector漏洞利用的蛻變》 http://www./article/14571.html 《Array Object Heap Spraying》 http://www.cnblogs.com/wal613/p/3958692.html |
|