前言 在前一部分中,我們介紹了從IE6到IE11的堆噴射方法,其實堆噴射只是一種手段目的還是為了實現(xiàn)最后的漏洞利用。在這一篇文章中,我們會根據(jù)時間順序來講解IE瀏覽器漏洞利用技術(shù)的發(fā)展,我們會把主要精力放在UAF漏洞的利用上面,同時會涉及一些其它類型的漏洞作為輔助以繞過漏洞緩解措施,這篇文章主要介紹技術(shù)發(fā)展脈絡(luò),實際的漏洞調(diào)試會放在下一章,期間我閱讀了大量的文檔、會議PPT和博客文章,在此也對前輩們的分享表示感謝。同時給大家分享兩句我很喜歡的話,一句來自大家應(yīng)該都很熟悉的陳皓大牛,一句來自charles petzold大家應(yīng)該都有讀過他的書 要了解技術(shù)就一定需要了解技術(shù)的歷史發(fā)展和進化路線。因為,你要朝著球運動的軌跡去,而不是朝著球的位置去,要知道球的運動軌跡,你就需要知道它歷史上是怎么跑的。 學(xué)習技術(shù)發(fā)展史的重要意義正在于此:追溯的歷史越久遠,技術(shù)的脈絡(luò)就變得越清晰。因此,我們需要做的就是確定某些關(guān)鍵的歷史階段,在這些階段,技術(shù)最天然、最本質(zhì)的一面將清晰可見。 首先簡單介紹一下本篇文章將要提到的漏洞類型,我們這篇文章主要會針對兩類漏洞進行描述,即越界訪問漏洞和釋放后重引用漏洞。這兩種漏洞的英文名稱分別為Out-of-Bound和Use-After-Free,因此我們通常簡稱這類漏洞為OOB和UAF。 1.越界訪問漏洞 越界訪問漏洞,個人認為越界訪問漏洞應(yīng)該是按照漏洞造成的效果進行劃分的,而不是依照漏洞成因進行的劃分。我認為如果是從成因的分類上來講,像堆溢出、整數(shù)溢出、類型混淆等都可以造成越界訪問漏洞。 越界訪問,所謂的訪問就是指越界讀和越界寫,在后面我們可以看出越界漏洞是比較容易利用,也是比較好用的一類漏洞,這里好用指的是效果比較好,一般通過這種OOB漏洞可以在IE瀏覽器中輕易的實現(xiàn)繞過ASLR的保護。 而這種漏洞的利用,一個共通點是要進行內(nèi)存布局(或稱為Feng shui技術(shù))。即把一些特殊的對象或者結(jié)構(gòu)布置在漏洞對象附近,否則讀寫都無從談起,我們會在后面展開來說這些內(nèi)容。 2.釋放重引用漏洞 Use-After-Free漏洞中文名為釋放后重引用漏洞,這種漏洞估計大家都比較熟悉。 所謂的“釋放重引用”是指在一塊內(nèi)存被釋放后在某處還保存有指向這塊內(nèi)存的懸垂指針,之后對懸垂指針進行了解引用(所謂的重引用)導(dǎo)致了漏洞的觸發(fā)。 我們分析UAF漏洞一般要搞清楚幾個關(guān)鍵點: 1.是什么對象發(fā)生的UAF? 2.UAF對象何時被分配、何時被釋放? 3.導(dǎo)致crash的流程是什么? 4.為什么會存在懸垂指針? 但是在早期的UAF漏洞利用來說,一些Hacker們往往只需要知道步驟2、3就可以實現(xiàn)漏洞利用。這是因為早期的UAF一般都是通過占位和堆噴射來進行利用的,比較簡單粗暴。 1.為什么IE中會存在大量的Use-After-Free漏洞? 我們的第一個問題是IE瀏覽器中為什么會爆出大量的UAF漏洞? 這個問題的提出并不奇怪,因為其它的軟件諸如Office Word的漏洞可能基本上都是一些堆棧溢出,而UAF則是鳳毛麟角。 IE瀏覽器中并不是沒有存在過棧溢出這些類型的漏洞,而是經(jīng)過了十余年的發(fā)展基本都已消耗絕跡,但是UAF漏洞“絡(luò)繹不絕”的本質(zhì)原因在于IE瀏覽器中存在著大量的各種類型的對象和其間互相關(guān)聯(lián)的關(guān)系,包括各種標簽和各種內(nèi)部數(shù)據(jù)結(jié)構(gòu)比如CElement就是代表元素對象的父類,舉例來看CButton是CElement的子類代表<Button>標簽。 這些html標簽和DOM Tree是由IE瀏覽器中的渲染引擎mshtml(就是所謂的Trident)負責解析的。html標簽在mshtml內(nèi)部就是由一個個的C++對象來進行表示的,同樣DOM樹也是通過一些數(shù)據(jù)結(jié)構(gòu)來進行描述(比如CTreeNode、CTreePos),這些對象之間存在復(fù)雜的相互關(guān)系。并且mshtml使用了引用計數(shù)的方法來跟蹤對象的使用情況。 我們可以通過泄漏的IE5.5源代碼來觀察這一點,雖然IE5.5版本對于我們來說已經(jīng)是相當?shù)墓爬狭耍瞧鋵嵰恍┖诵牡牟糠诌€是相當相近的。 如下是IPrivateUnknown接口,這個接口在我們源碼中存在著如下的繼承關(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; }; 在此我推薦閱讀以下兩篇文章,可以增進對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漏洞是我們這篇文章的主題,在分門別類的進行討論之前,我們首先介紹一些基礎(chǔ)知識。我們在前面介紹了UAF漏洞的一些信息,對于UAF漏洞的利用無論在什么時期,一個通用的步驟就是在UAF對象被釋放之后馬上去分配一個相同大小的內(nèi)存塊,我們稱這一步操作為“占位”。占位的原理在于堆分配的機制,當一塊堆內(nèi)存被釋放后出于效率的考慮會被保存在一些結(jié)構(gòu)中以便于再次的分配。占位就是利用這一點,通過分配相同大小的堆內(nèi)存試圖重用UAF對象的內(nèi)存,對Linux堆有了解或是打過CTF的同學(xué)應(yīng)該都比較熟悉這一點了。為了成功實現(xiàn)占位,一般是多次分配相同大小的內(nèi)存以保證成功率。 需要說明的一點是,不是所有的UAF漏洞都是可以利用的,因為一些漏洞無法進行占位。比如有的漏洞它的對象釋放和重用操作就在同一個函數(shù)中,剛剛釋放完馬上就重用了,這種情況根本沒有機會去進行占位,從而無法進行利用。 我們說了這么久的占位,其實占位的目的是為了控制對象的內(nèi)容。同樣目的的操作,還有挖坑法(make hole),挖坑法是指在布局好的內(nèi)存中釋放一個指定大小的塊,好讓目的對象落在我們布局的內(nèi)存中,我們會在后文提到這一點。還有內(nèi)存未初始化漏洞的利用也與之類似,內(nèi)存未初始化漏洞是指分配一塊內(nèi)存后未經(jīng)初始化就直接進行使用,我們?yōu)榱丝刂莆闯跏蓟瘜ο蟮膬?nèi)容會先釋放一些與之相同大小的已布置好內(nèi)容的內(nèi)存,然后讓未初始化對象來重用我們的內(nèi)存。 接下來我們就根據(jù)歷史發(fā)展來討論利用技術(shù),可以看出隨著歷史的向前漏洞利用技術(shù)有了很大的發(fā)展,相比早期的利用技術(shù)現(xiàn)在無論是在思路還是在手法上都是發(fā)生了質(zhì)的飛躍。 3.IE6漏洞利用(史前時代) 我們把IE6作為IE漏洞利用的開端,我們稱之為史前時代,說到史前我們可能會想到刀耕火種、茹毛飲血。此時的IE漏洞就是處于這樣一個野蠻生長的時代,漏洞利用技術(shù)簡單粗暴導(dǎo)致網(wǎng)馬大量橫行。主要原因在于IE6時代的瀏覽器版本不支持DEP等漏洞緩解措施(雖然此時操作系統(tǒng)已經(jīng)支持DEP),導(dǎo)致漏洞利用的成本低廉,但是也因此流傳下來一些“遠古神話”,比如經(jīng)典的0x0C0C0C0C。 這一時期由于Active X插件作者的水平參差不齊,因此大量的控件存在有諸如棧溢出之類的簡單漏洞,利用方式也極為簡單粗暴配合堆噴就可以實現(xiàn)利用,這些漏洞我們簡單略過不再詳述。 我們把關(guān)注重點放到此時的UAF漏洞上面,通過我們前面對UAF漏洞的簡單介紹就可以看出,UAF漏洞與棧溢出有著本質(zhì)不同。棧溢出可以簡單直接的控制返回地址從而劫持執(zhí)行流程,但是UAF往往是處于堆上并沒有直接劫持流程的途徑。為了能夠在堆上劫持指令執(zhí)行流程,前輩們想出了劫持虛函數(shù)調(diào)用的方法。 我們首先簡單介紹一下虛函數(shù),在C++程序中,如果一個類存在虛函數(shù)那么當這個類實例化對象后,對象的前4個字節(jié)就是虛函數(shù)表的指針,當我們調(diào)用虛函數(shù)時實際上是到虛函數(shù)表中尋找函數(shù)指針。接下來,我們就通過這一點來進行利用。 我們首先通過占位來控制UAF對象的內(nèi)容(如果你不理解這一步,可以往前看一看),控制了對象的內(nèi)容就相當于控制了虛函數(shù)表的指針。接下來我們需要一個穩(wěn)定可達的地址,因此我們使用上一篇文章講過的堆噴射,然后把虛表指針指向我們噴射的內(nèi)存地址,這樣一旦觸發(fā)漏洞就會把我們的噴射內(nèi)存當作虛表來執(zhí)行了。 為什么一觸發(fā)漏洞就會把噴射內(nèi)存當作虛表來執(zhí)行呢?如果沒有調(diào)試過IE漏洞可能會提出這個問題,因為我們實際去調(diào)試漏洞就會發(fā)現(xiàn)事實上UAF漏洞觸發(fā)后基本都會crash在虛函數(shù)調(diào)用處,如果你發(fā)現(xiàn)windbg停在一個莫名其妙的地方很可能是因為沒有開啟頁堆,可以使用!gflags.exe -i +hpa進行開啟,關(guān)于頁堆可以學(xué)習一下張銀奎老師的《軟件調(diào)試》。(此外新手可能會發(fā)現(xiàn)明明異常了卻沒有停下來,可能是沒開啟子進程調(diào)試,主要是對于IE8以后這種多進程瀏覽器來說。) 根據(jù)我們上面的描述可以看出,我們是在把噴射的內(nèi)存當成虛表。但是當我們調(diào)用虛函數(shù)時,往往是下面這個樣子的: 1 2 mov eax,[ecx] call [eax+4] 這兩條指令意味著,噴射的內(nèi)存不僅會被當成虛表還會被當成指令來執(zhí)行。并且更糟糕的情況是:這里我們不能確定堆噴射的準確分配地址,就是說我們不能確定堆表指針到底噴射在哪里。這時就對我們的噴射提出了要求,我們需要尋找一個既可當作地址解釋又可以當作無意義指令解釋的值。 在這種情況下“上古傳說"0x0C0C0C0C就誕生了,如果我們使用0x0C0C0C0C作為噴射的內(nèi)容的話,當mov eax,[ecx]時就會取到0x0C0C0C0C作為指針來進行跳轉(zhuǎn),call [eax+4]會把0x0C0C0C0C的0x4處偏移取出并call,當然其結(jié)果依然為0x0C0C0C0C,這樣call 0x0C0C0C0C會執(zhí)行指令0x0C,而0x0C相當于nop就會最終執(zhí)行到shellcode了。當年有很多這樣的通用地址存在比如0x0D0D0D0D、0x06060606。 這種利用方式簡單粗暴卻又有效,因此我們稱為史前時代,就像TK教主說的一樣: 在當年無 DEP 的環(huán)境下,幾乎完全不懂漏洞原理的人,知道去 Heap Spary 0x0C0C0C0C 就能搭積木一樣寫出 Exploit,而且還很通用。 當然,對于不涉及虛表訪問的利用來說,使用0x0c0c0c0c是完全沒有意義的。不過這個地址已經(jīng)成為一個"上古神話"了,所以我們還是會經(jīng)??吹玫剿?,甚至于一些安全軟件一旦發(fā)現(xiàn)這個值就會報警。 4.IE8早期漏洞利用(石器時代) 前面我們說IE6時期是史前時期,因為那時的漏洞利用簡單粗暴。相比于當時,IE8時代的利用技術(shù)向前走了一大步,不過因為安全體系的問題早期的IE8利用依然只能稱為是石器時代,還是相當?shù)脑肌?/p> 自IE8開始,DEP和ASLR成為瀏覽器中默認啟用的緩解措施,如何bypass ASLR和DEP成為了攻擊者首要面對的問題。我們簡單介紹一下DEP和ASLR,如果是熟悉Linux的同學(xué),那么Linux下的NX保護與DEP是很類似的,都是把一些非代碼段內(nèi)存設(shè)為不可執(zhí)行來阻止攻擊者運行shellcode。在其它的軟件中bypass DEP通常使用ROP技術(shù),但是由于IE幾乎都是基于堆的漏洞不存在直接進行ROP的條件所以并不能通過簡單的ROP實現(xiàn)bypass DEP。而ASLR會使得模塊裝載的地址變得不確定,對漏洞利用有一些了解的同學(xué)肯定知道Rop技術(shù)是依賴于一些rop gadgets來進行不斷的跳轉(zhuǎn)利用的,ASLR的啟用會直接妨礙我們獲取rop gadgets。 不過對于早期的利用,ASLR并沒有對利用者造成太大的困擾。因為ASLR早就在諸如Office Word之類的軟件中啟用了,Hacker們直接套用了在這些軟件中的做法即利用一些未開啟ASLR的模塊進行利用。因為當時很多的模塊并不支持ASLR因此加載在固定基地址。這種方法也是比較簡單粗暴的而且通用性比較差,比如以前在IE中常用的Java6的msvcr71.dll,如果目標并沒有安裝JRE或者版本不對利用都不能成功。 因為此時仍然比較原始,所以我們稱之為石器時代。事實上,今天的應(yīng)用程序不支持ASLR的已經(jīng)非常少見了,想通過不支持ASLR的模塊來實現(xiàn)ROP已經(jīng)不大可能了。所以我們把完整的利用方法放到下一章中詳述。 5.IE8瀏覽器結(jié)合信息泄漏利用(鐵器時代) 據(jù)說人類跟動物的區(qū)別是人類會使用工具,那么這一時期利用技術(shù)的進步堪比從石器進化到鐵器。 這一時期的標志事件是Peter Vreugdenhil在Pwn2Own2010中攻破IE8項目,這一過程中的技術(shù)手段對后來的利用技術(shù)發(fā)展有著重要的作用。Peter Vreugdenhil利用IE8的手段是把一個OOB漏洞與一個UAF漏洞相互結(jié)合,我們首先來說OOB漏洞。Peter Vreugdenhil通過內(nèi)存布局把BSTR布置在存在OOB的對象后面,目的是進行信息泄漏,通過越界寫來改變BSTR的長度,實現(xiàn)了越界讀。 我們在前面說過BSTR不是簡單的Unicode字符串,BSTR的結(jié)構(gòu)由4字節(jié)的長度(size)域、2字節(jié)的結(jié)束符()加上Unicode字符串構(gòu)成。通過我們精心構(gòu)造內(nèi)存布局,使BSTR對象緊隨漏洞對象的后面。之后再在BSTR后面再放置目標對象,這樣當觸發(fā)漏洞對象發(fā)生越界訪問的時候就可以覆蓋掉BSTR結(jié)構(gòu)的size域。一旦我們把size域覆蓋為更大的數(shù)值,我們就能夠使得BSTR發(fā)生越界讀(因為BSTR只可讀不可寫)。然后通過js腳本讀取BSTR字符串,就能夠讀到BSTR之后的對象。我們的目的是獲取后面對象的虛表地址(首4個字節(jié))。如果你想了解的更詳細可以參見(http:///Pwn2Own-2010-Windows7-InternetExplorer8.pdf ) 為什么獲得虛表地址就可以bypass ASLR呢?因為對于C++程序來說虛函數(shù)表是被編譯在全局數(shù)據(jù)段的,就是說對于模塊的基地址的偏移是固定的。我們通過泄漏的虛函數(shù)表的地址減去偏移就可以知道對象所處的dll模塊的基地址,也就可以使用這個模塊中的gadgets了。 這種方法有兩個需要解決的問題:第一是如何構(gòu)造穩(wěn)定的內(nèi)存布局使我們上述的內(nèi)容得以實現(xiàn)。第二是當我們覆蓋成功后,如何通過javascript腳本層面上的操作把值獲取到。其實我們后面要講到的方法都面臨著這兩個問題。 由于這種利用較為簡單,可以直接參考泉哥的著作《漏洞戰(zhàn)爭:軟件漏洞分析精要》里面第三章的CVE-2012-1876的利用分析,其使用的方法就是通過BSTR進行泄漏,我們也會在下一篇中給出實際的漏洞調(diào)試。 單單繞過ASLR是無法實現(xiàn)漏洞利用的,因為DEP的存在我們沒有辦法在堆上執(zhí)行指令。為此Hacker們想了很多辦法,其中我認為最早實現(xiàn)成功利用的依然是Pwn2Own 2010上Peter Vreugdenhil使用的方法,雖然與我們這里講的不完全相同,但是我覺得是Peter Vreugdenhil方法的進化版。我們忽略Peter Vreugdenhil的方法(感興趣的可以查看上面的連接),我們使用的手段是stack pivot,所謂stack pivot就是通過mov esp,eax、xchg esp eax等指令來實現(xiàn)把棧轉(zhuǎn)移到堆上,因為一般的UAF漏洞觸發(fā)時我們都可以控制至少一個寄存器的值。通過把esp指向我們噴射的內(nèi)存,我們就可以把堆偽造成棧,從而像普通的棧溢出一樣進行ROP,通過執(zhí)行ROP最終實現(xiàn)代碼執(zhí)行。 但是這一利用方法首先要確保的是我們要能夠精準的計算堆噴射的地址,因為堆不可執(zhí)行所以我們不能再依賴于用于緩沖的nop指令了。好消息是我們在前一篇文章中已經(jīng)講過準確計算的原理和實現(xiàn)了,這里再簡單復(fù)述一下。當我們大量分配堆塊時可以發(fā)現(xiàn)地址的最低幾位是一直不變的,地址改變的熵只是固定的地址高位并且堆塊的分配相當?shù)姆€(wěn)定。這樣如果我們使偏移都落在地址的高位,那么我們的指向就會是整塊進行偏移,從而保證了每次指向的都是計算好的準確的地址。 舉個例子:我們可以以每個塊為單位計算出ROP鏈第一條地址的偏移,然后其實我們可以想一下0x0C0C0C0C這個地址還有沒有用?在這種利用環(huán)境下,第一不需要跳板指令,第二我們跳轉(zhuǎn)目的地址是精確的,那么0x0C0C0C0C這種地址就根本沒有存在的價值了。我們要的就只是一個堆噴射可達的穩(wěn)定的地址。 無堆噴射,通過ANIMATECOLOR對象實現(xiàn)利用 這種方法不需要進行堆噴射就可以實現(xiàn)利用,堆噴射其實并不能說是一種優(yōu)雅的利用方法,因為分配內(nèi)存需要一定的時間,而且如果目標機器的配置較低的話可能會導(dǎo)致卡頓從而被目標察覺。我之前在binvul上看到過一些所謂的“不彈不卡不噴射不風水”的樣本其實指的就是這種技術(shù)。 ANIMATECOLOR是IE8版本起提供的一種對象,由于這種對象的特殊構(gòu)造所以可以不使用堆噴射來實現(xiàn)利用,我們在下一篇實際漏洞調(diào)試時再來進行分析。 6.結(jié)合Flash的利用(中世紀) 到這里瀏覽器利用技術(shù)又是一個飛躍,結(jié)合flash利用雖然不能說特別優(yōu)雅(因為要依靠第三方),但中世紀是文藝復(fù)興的先聲,可以說自此之后利用技術(shù)又進入了一個發(fā)展的新巔峰。 這種利用技術(shù)不是來自于Pwn2Own也不是來自于某次會議的分享,相反,隨著時間的發(fā)展,在2013年網(wǎng)上流傳出了一些無需多漏洞結(jié)合使用,通過單一漏洞就可以bypass緩解措施+執(zhí)行代碼的exp樣本,這些exp樣本應(yīng)該是用于實際攻擊的武器。其主要特點是結(jié)合了flash進行漏洞利用,這種利用技術(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ù)可以只憑借一個單一的漏洞實現(xiàn)bypass全部的緩解措施并且執(zhí)行最終的shellcode,這一點是以前的exploit所做不到的事情。 我們簡單的概括一下利用的方法,我們先忽略漏洞的細節(jié)簡單的認為它是一個0x90個字節(jié)的堆塊發(fā)生的溢出。我們首先分配一系列0x90大小的Vector對象,對于儲存數(shù)字的Vector來說每個數(shù)字占8個字節(jié),16個數(shù)字加上16字節(jié)的固定結(jié)構(gòu)正好滿足0x90的大小。 我們在vector對象布置完成之后,通過代碼來釋放一些0x90大小的vector,再觸發(fā)漏洞。之后會分配具有溢出的0x90大小的堆塊,因為尺寸與我們之前釋放的vector尺寸相同,根據(jù)堆的特性漏洞堆塊會重用我們之前釋放的vector對象內(nèi)存。這一步操作稱為挖坑(make holes),挖坑的目的是為了使得漏洞堆塊處于vector對象的包圍之中。 下一步,我們只需要利用溢出就可以覆蓋掉相鄰vector對象的“Number_of_elements”域。 覆蓋的結(jié)果是使得相鄰的vector可以發(fā)生越界訪問,通過操作這個越界的vector我們又可以覆蓋下一個vector的“Number_of_elements”域,但這次我們可以直接把“Number_of_elements”域改的很大,從而實現(xiàn)了整個進程地址空間的任意讀寫。 一旦實現(xiàn)了整個內(nèi)存空間的進程讀寫,就可以做到bypass DEP和ASLR了。 如果說這次利用只是因為漏洞本身有比較合適的尺寸便于布局、有直接的溢出便于覆蓋結(jié)構(gòu)。那么陳小波前輩發(fā)布的《ASLR Bypass Apocalypse in Recent Zero-Day Exploits》中就給出了一個通用的思路,其中提到了很重要的一點就是:如何把一個常規(guī)的UAF漏洞往我們上面說的Flash vector越界寫上面進行轉(zhuǎn)化。對于這個問題作者提供了如下的思路:以CVE-2013-0634為例,這是一個在IE瀏覽器中常見的UAF漏洞,在利用這個漏洞時exp作者在代碼執(zhí)行路徑上發(fā)現(xiàn)了一條指令: 1 or dword ptr [esi+8],20000h 其中esi的值是我們可控的(來自UAF對象,可以通過占位進行控制),作者把它指向布置好了的Vector對象的長度域,在執(zhí)行了or之后長度域會變大從而使得這個vector可以進行越界操作。之后可以通過這個vector越界寫緊鄰的下一個vector的長度域從而實現(xiàn)了整個進程地址空間的任意讀寫。此外還要解釋一下為什么可以知道Vector對象的長度域的地址, 之后的IE瀏覽器利用從基本思想上發(fā)生了轉(zhuǎn)變,攻擊者不再追求結(jié)合多個漏洞泄漏信息再進行堆上ROP,而是繼承了flash vector的任意讀寫轉(zhuǎn)化思路,試圖從UAF轉(zhuǎn)化到任意地址讀寫,再通過任意地址讀寫來實現(xiàn)繞過緩解措施。 7.UAF轉(zhuǎn)化與Element Attribute(啟蒙時代) 之后漏洞利用進入啟蒙時代,相比flash利用這一時期的優(yōu)點是不再依賴于flash模塊。這樣可以提高漏洞利用的成功率和降低成本,因為此時一個漏洞就可以實現(xiàn)多個漏洞的利用效果并且在flash利用爆發(fā)后安全軟件對夾雜flash的頁面十分敏感,不依賴flash可以提高漏洞利用的成功率。 在《A BROWSER IS ONLY AS STRONG AS ITS WEAKEST BYTE》這篇文章中,作者以CVE-2013-3147為基礎(chǔ)詳細講解了如何從crash地點進行分析來尋找一條合適的代碼路徑把UAF轉(zhuǎn)化成inc [address](絕對地址加),并且避開虛函數(shù)調(diào)用以免引發(fā)crash。簡單的概括就是查找crash附近的代碼流程,尋找有沒有寫原語,如果存在這樣的原語就想辦法滿足邏輯條件把執(zhí)行流程引導(dǎo)寫原語上去。 值得注意的是作者在利用這個任意地址加的過程中并沒有依靠flash vector,而是通過噴射Element Attribute來實現(xiàn)利用。首先簡單介紹一下Attribute是什么,如果你有看過HTML那么應(yīng)該知道一些標簽是具有屬性的,比如每個標簽都有id屬性用做唯一的標識。對應(yīng)于底層實現(xiàn)來說,每個DOM元素對應(yīng)的CElement結(jié)構(gòu)中也會有指針指向Attribute Array,每個屬性占其中一項。那么Element Attribute是如何實現(xiàn)利用的呢? 首先我們忽略漏洞的細節(jié),只看漏洞導(dǎo)致的效果,經(jīng)過轉(zhuǎn)化操作這個UAF漏洞可以引導(dǎo)到如下的路徑上 而第二個DWORD的值為屬性名的哈希值,第三和第四個值為實際的屬性內(nèi)容,如果屬性內(nèi)容是諸如字符串這樣的值,那么它會是一個指針。 作者的核心思路是對第三個DWORD那個指針進行加1操作,因為是以字節(jié)為單位進行加1,所以實際的操作效果可能是指針偏移0x1、0x100、0x10000、0x1000000。在這種思路之下作者進行了內(nèi)存布局,通過構(gòu)造相同大小的BSTR字符串和一個元素來使得它們彼此相鄰的分配(相同大小通過計算可以輕易的得到,而且也正是因為它們大小相同所以才會發(fā)生彼此相鄰的分配),在布局完成之后對指針進行加1操作就可以讀出后面元素的內(nèi)容,在實際利用過程中布局要更加復(fù)雜一些不過原理是一致的。 實際利用過程中作者一次性創(chuàng)建了含有0x7FFE個屬性的元素,然后復(fù)制它直到大小為0x800000個字節(jié)。然后對這些元素進行遍歷,每隔0x1000個屬性就把它的值設(shè)置為一個0x8A大小的字符串,這個設(shè)置會導(dǎo)致在內(nèi)存中分配0x8A字節(jié)的字符串,然后馬上創(chuàng)建一個body元素并添加9個默認屬性(大小正好是0x8A)這樣就做到了BSTR和元素的緊鄰分配。接下來就像我們上面所說的對指針加1就能讀到body元素的內(nèi)容了。因為body默認屬性中包含一些域,通過讀取它就可以算出mshtml.dll的基地址。 然后作者在這個基礎(chǔ)上繼續(xù)進行改進,因為作者認為mshtml.dll的版本變化比較多對于利用不是很理想,而且現(xiàn)在我們做的還只是泄漏操作沒有實際的進行執(zhí)行流劫持,而我們這一階段的主題就是只通過單個漏洞來實現(xiàn)完整的利用。作者為了實現(xiàn)流程控制對屬性表進行了覆蓋操作,但是又會受到低碎片堆機制的限制,為此又要偽造堆頭結(jié)構(gòu)。可見這種利用方法還是比較麻煩的,但是對Element Attribute結(jié)構(gòu)的利用思路對后來的漏洞利用思路有很大的幫助。 之后在2014年,這個時候Ivan Fratric的《Exploiting Internet Explorer 11 64-bit on Windows 8.1 Preview》發(fā)布出來。這篇文章的意義在于,作者針對javascript array對象進行了分析,然后對array對象進行Feng shui布局并且通過它的capacity域?qū)崿F(xiàn)了利用。由于js引擎是根據(jù)capacity域?qū)?shù)組大小進行判斷的,因此我們一旦篡改了capacity域就可以對數(shù)組進行越界訪問。在下一階段的利用中,我們就會看到array object在漏洞利用中起到的作用。 此外在2015年的Pwn2Own上,360 vulcan團隊就是通過Element Attribute對IE11瀏覽器進行的利用。不過與我們這里的情形不同,vulcan利用的漏洞恰好就是在處理Element Attribute時出現(xiàn)的未初始化問題,由于與文章主題無關(guān)這里就不贅述了,不過相信讀完本文之后你就可以理解古河講的利用思路了,利用的詳情可以查看http://www./course/52149。 8.IE11與針對jscript9引擎的攻擊(近現(xiàn)代) CanSecWest2014上,ga1ois在議題《The Art of Leaks》中討論了幾個很關(guān)鍵的問題。 第一是自IE9以后引入的jscript9引擎——jscript9.dll使用與以前不同的custom heap,而且這個custom heap并沒有做任何的分配隨機化措施,這一點給我們進行內(nèi)存布局提供了可能。 第二是從UAF轉(zhuǎn)化為任意地址讀寫的過程中可能因為虛表訪問而導(dǎo)致crash和如何避免發(fā)生這種crash。 在IE9之前的版本中,javascript是由javascript解析引擎——jscript.dll負責解析的,這個dll在分配內(nèi)存時使用的是系統(tǒng)的進程堆。而在最新的javascript解析引擎——jscript9.dll中,在分配一些對象時引擎會使用custom heap,這個custom heap是由jscript9自己負責管理和維護的。并且這個custom heap在分配時沒有進行隨機化處理,以至于攻擊者可以通過布局一些對象(所謂的feng shui技術(shù))來預(yù)估出對象所處的地址。 其中直到0xf000之前的都是我們的array object填充數(shù)據(jù),而自0xf000起是我們想要的目標對象,這里以int32Array作為目標對象的例子。 因為后續(xù)我們還會涉及到int32Array這個對象,所以我們這里詳細的介紹一下。int32Array屬于Typed array的一種,根據(jù)MDN的介紹Typed array有以下幾種 我們知道javascript是一種腳本語言,是難以像C語言一樣表示一些底層數(shù)據(jù)類型的,Typed array的設(shè)計就是為了解決這個問題。我們雖然可以直接使用new來創(chuàng)建一個Typed array對象,諸如 其中Arraybuffer Data就是直接保存數(shù)據(jù)的區(qū)域,并且這塊內(nèi)存是分配在process Heap上的。 一旦可以預(yù)估出對象的地址那么就可以通過把UAF轉(zhuǎn)化為絕對地址寫去篡改Int32Array對象的長度域,來實現(xiàn)Arraybuffer Data的越界讀寫。因為Arraybuffer Data是儲存在process Heap中的因此需要一個分配在process Heap上的對象來配合利用。這里作者使用的是LargeHeapBlock,因為這個對象處于process Heap中,并且恰好存在合適的域來實現(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進一步發(fā)展了這一技術(shù),代碼和文檔可以在作者github中找到(https://github.com/exp-sky)。與ga1ois的不同之處在于exp-sky沒有使用typed array進行布局,而是將IntArray Object作為目標對象進行布局。這一操作的優(yōu)點在于IntArray全部都是基于custom heap進行操作的,如果你還記得我們上面講的內(nèi)容的話,你應(yīng)該知道我們在對typed array進行篡改操作后進行越界編輯的是Arraybuffer Data,而這塊內(nèi)存是存放于process heap中的,這就意味著我們還要進一步的對process heap進行布局,而這種方法則完全沒有這個必要。 注意這兩個結(jié)構(gòu)都處于Custom Heap并且是分配在一起的。 因此噴射IntArray相比前面的方法要更方便也更容易控制,由于ArrayBuffer對象存在有保存當前緩沖區(qū)大小的域(buffer_size),只要通過絕對地址寫改寫這個域為很大就可以轉(zhuǎn)化為任意內(nèi)存讀寫了,之后再修改相鄰塊的域這一點與前面的技術(shù)是相同的。 總體來說,這一時期的利用思路基本都在于噴射一些關(guān)鍵的對象,并結(jié)合各種feng shui技術(shù)(尤其是jscript9中的)進行布局。然后試圖把UAF轉(zhuǎn)化為絕對地址寫,來寫我們噴射對象的關(guān)鍵域從而實現(xiàn)從UAF到任意地址讀寫的跨越。 一旦獲得了任意地址讀寫就相當于可以讓攻擊者進行隨意利用,這時各種漏洞緩解措施就不再能夠阻擋攻擊者的腳步了。 這里我使用了一張demi6od在《Smashing the Browser》議題中使用的圖,這張圖很好的說明了我們所講的思路。 后記 其實這一系列的文章,我在去年10月份的時候就已經(jīng)寫完了,但是一直在硬盤里放了近半年都沒有投出來。我主要是考慮到這系列文章涉及的話題太廣、內(nèi)容太多、歷史又太悠久,考慮到自己僅是個大二學(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 |
|