文偉平:謝謝主持人,非常高興,也有這樣的機(jī)會來參加第三屆網(wǎng)絡(luò)安全大會,今天我看到這個場景非常感動,這么多參會者還坐在地下,外圍也那么多參會者站著聽著我們的演講。我們北大團(tuán)隊也參加了第一次的網(wǎng)絡(luò)安全大會,也派了一個代表,所以我這里有一些內(nèi)容可能曾經(jīng)在第一屆網(wǎng)絡(luò)安全大會和第一屆互聯(lián)網(wǎng)網(wǎng)絡(luò)安全大會講過,如果有一些參會者聽過的話,我可能會說的快一點(diǎn)。
今天和大家探討的主題叫”軟件安全漏洞挖掘技術(shù)”。軟件安全漏洞挖掘,國內(nèi)還有叫漏洞分析,漏洞分析和漏洞挖掘業(yè)界也是有區(qū)分的,有些就是把漏洞挖掘歸在漏洞分析,我們這個意義上的漏洞挖掘是指對位置漏洞的挖掘。
當(dāng)前的技術(shù)發(fā)展,大家也知道,漏洞挖掘本身是很難的問題。大家發(fā)現(xiàn)Windows7發(fā)現(xiàn)很多遠(yuǎn)程管理的漏洞,但Windows7發(fā)布之后,大家發(fā)現(xiàn)遠(yuǎn)程管理漏洞,尤其系統(tǒng)級的變得比較少了,實際這和微軟SDL開發(fā)模式有一定的關(guān)系,他們有安全的開發(fā)平臺。Windows7操作系統(tǒng)里實際它也引入了很多安全機(jī)制,上午TK在”內(nèi)存20年”里也介紹到了一些安全機(jī)制,但沒有詳細(xì)展開,StackCookie他可能列了1997年的幾篇論文,也就是通常所說的GS,還有SafeSEH,DEP是數(shù)據(jù)執(zhí)行保護(hù),和地址空間的隨機(jī)化,也就是說這些安全機(jī)制的涌入,使得我們能找到安全隱患的點(diǎn)或者Bug,如果Bug不能夠被利用其實還不能算是漏洞,即使我們確定了可能是個安全隱患,但它卻不能夠被利用,使得我們在挖掘一些安全漏洞也變得越來越難。
實際漏洞挖掘技術(shù)也是在發(fā)展的,既然早期我們主要是通過ST、CTOI或者GES、SGANF(音)這樣一些漏洞的函數(shù),構(gòu)建函數(shù)模型來進(jìn)行漏洞挖掘。在后期我們會引入路徑模型的概念,包括原代碼審計系統(tǒng)系統(tǒng),二進(jìn)制代碼反饋之后也是一種源碼,也就是說我們可以根據(jù)代碼直接的上下文關(guān)系,語義解析構(gòu)建出一些路徑模型來挖掘漏洞。系統(tǒng)的安全對抗也是發(fā)展的,既然有了新的技術(shù)和安全機(jī)制同樣也會推出對抗的技術(shù),例如數(shù)據(jù)執(zhí)行保護(hù)制,可以通過ROP構(gòu)造出來各種各樣的Gaget,調(diào)用系統(tǒng)里相關(guān)的函數(shù),因為攻擊者攻擊對方之后實際更多是被攻擊機(jī)器上的資源完成他攻擊的過程。
針對地址空間的隨機(jī)化,我們知道對噴(音)是最典型的,還有AC3里一些針對漏洞的GsBre(音),還有TK之前提出來的像UZDate數(shù)據(jù)解構(gòu),他們是能構(gòu)造出來通用Shellcode的一些方法,能夠提高漏洞被利用的成功概率。
以Windows系統(tǒng)為例介紹一下它的內(nèi)存保護(hù)機(jī)制,當(dāng)傳統(tǒng)內(nèi)存機(jī)制,GS、SafeHEP、SafeSEH、DEP和SLF,Windows8里也引入了新的能夠檢測到ROP的方法。對堆進(jìn)行了更多的改進(jìn),比如隨機(jī)化的LFH,對頁面屬性的保護(hù),對其他內(nèi)存方面比如虛指針也提供了相應(yīng)的安全機(jī)制,對于空頁面、內(nèi)存分配的隨機(jī)化,(PPT)大家看右邊這個圖,GS方面它也進(jìn)行了積極的增強(qiáng),也就是StackCookie,Windows7和Windows8最大的一個區(qū)別,就是在Cookie生成算法里采用了Intel的SQL-key這樣的算法和技術(shù),使得Cookie更難以進(jìn)行猜測。在SL方面,他又提出了高算地址的隨機(jī)化,我想研究過Win8或調(diào)試過Win8的系統(tǒng)安全人員應(yīng)該都很清楚它的機(jī)制。DEP里它也提出檢測ROP的機(jī)制。
軟件、漏洞挖掘技術(shù),三個標(biāo)紅的可能是我們在一些大會上面跟大家交流過的,漏洞挖掘技術(shù)只是一些思路,并沒有很深的技術(shù),大家一聽可能就很明白。第一種技術(shù)應(yīng)該是很多廠商廣泛使用的一種漏洞挖掘技術(shù),基于Crash信息的,這里的Crash信息可能是基于單機(jī)的,實際還有很多網(wǎng)絡(luò)上的Crash信息是可以用的。如果微軟Crash信息收集服務(wù)器沒有采用加密形式進(jìn)行傳遞,這些信息對我們是非常有用的,所以對于微軟的Windows系統(tǒng)我們更多的是采用本地的,對于應(yīng)用軟件,就是對網(wǎng)絡(luò)上傳輸?shù)腃rash信息是很有分析價值的。
以微軟Windows為例,Windows出現(xiàn)藍(lán)屏事件時會有系統(tǒng)轉(zhuǎn)存,轉(zhuǎn)存模式有三種:一是完全的淡化,把當(dāng)前物理內(nèi)存里的所有信息都存下來;二是核心內(nèi)容的存儲,除了進(jìn)程之外的信息我們把它Download下來,三是小內(nèi)存的存儲,以16位為單位進(jìn)行轉(zhuǎn)存。得到這些信息之后,就可以通過微軟自身提供的Win DBG進(jìn)行分析,每一個出錯的信息都可以形成陷阱針,我們這個陷阱針我們可以通過bing看到它當(dāng)時出錯的場景,比如堆棧是什么情況,在一條什么指令上出錯,可能大家從這條指令就能夠看出,它在讀一些不應(yīng)該讀的地址,就是讀出一個錯誤。
回溯之后,我們可以把整個函數(shù)調(diào)用順序清晰地展示出來。最后我們能看到,可能這個函數(shù)是wingzk!SfnINSTRING出現(xiàn)的問題,下一步我們可以借助強(qiáng)大的反饋鏈平臺,像IDA來進(jìn)一步判斷它是不是存在邏輯的缺陷,判斷它這個漏洞有沒有可能被進(jìn)行利用。
我們判斷的一個依據(jù),看看用戶態(tài)里的參數(shù)或數(shù)據(jù)能不能夠傳遞到內(nèi)核態(tài)里,所以,我們一步步進(jìn)行回溯,最后發(fā)現(xiàn)從用戶態(tài)空間傳遞過來的參數(shù)沒有做任何判斷,而”esi+8″這個地址可以被我們指定,這種情況下面就意味著我們能夠發(fā)現(xiàn)內(nèi)核里讀的錯誤,這也是我們MS11-054發(fā)現(xiàn)的過程,也是我們團(tuán)隊發(fā)現(xiàn)的一個漏洞,這個漏洞也已經(jīng)提交給微軟了。
第二種方法也比較簡單,基于這樣的假設(shè),也就是假設(shè)我們給廠商給自己產(chǎn)品打補(bǔ)丁時,打的補(bǔ)丁存在一些安全隱患,或者打的不完備,因為軟件廠商發(fā)現(xiàn)發(fā)現(xiàn)自己的產(chǎn)品出來漏洞之后一定希望用最小的代價去修復(fù)當(dāng)前這個漏洞,所以,它一般比較注重當(dāng)前漏洞點(diǎn)的修補(bǔ),而很少考慮漏洞上下文的環(huán)境,尤其Windows這種大型邏輯上它是很嚴(yán)謹(jǐn)?shù)模珜芏嗟倪壿嫍l件在別的地方可能也存在相應(yīng)的改變,也就是它不能考慮到整個系統(tǒng)或者第三方代碼會給我們變量和邏輯條件帶來影響,這樣我們可以形成了參考,安全補(bǔ)丁比對邏輯挖掘的思路。這種技術(shù)我們在清華大學(xué)學(xué)報上面已經(jīng)形成論文,大家可以去下載。其實思路是很簡單的,也就是說我們可以通過路徑查找能夠找出來所有可能能夠執(zhí)行的路徑。
進(jìn)一步對這個邏輯條件進(jìn)行相應(yīng)判斷或者進(jìn)行約束,最后進(jìn)行求解,能不能夠找到繞過這個邏輯條件去執(zhí)行到漏洞點(diǎn)的路徑,如果能找到的話,就意味者這個漏洞修補(bǔ)可能是不完全的。
這里有個典型的漏洞,這個漏洞應(yīng)該說是已經(jīng)公開的。漏洞之前和之后實際在前面就是加了一個邏輯條件和框段,同時Windows系統(tǒng)和其他開發(fā)者在其他地方又有這個地方進(jìn)行了修改,如果我們采用某一種方法,能夠把它的條件先進(jìn)行重置,這種情況我們就可以把以前的漏洞進(jìn)行重現(xiàn)。
舉例,MS10-010,是我們團(tuán)隊成員在分析MS10-011這個漏洞和補(bǔ)丁分析出來的一個漏洞,當(dāng)時這個漏洞的D點(diǎn)和P點(diǎn)實際是在不同的函數(shù)里,也就是說實際增加了運(yùn)行到漏洞點(diǎn)的邏輯條件,但這個邏輯條件它是可以通過普通用戶構(gòu)筑一些特定函數(shù)后來進(jìn)行修改的,既然我們自己也有編程的基礎(chǔ),代碼方面的技術(shù),自己可以通過編程直接改變這個條件,從而觸發(fā)原來的一個漏洞,所以這很巧一個是MS10-011,一個是MS10-010,實際他們是一樣的漏洞,是屬于客戶端子系統(tǒng)的漏洞。
第三種方法,系統(tǒng)內(nèi)核函數(shù)的無序調(diào)用,這里面不僅僅是內(nèi)核函數(shù),也可以API函數(shù),Win7、Win8出現(xiàn)之后,系統(tǒng)漏洞的確很難繼續(xù)挖掘,我們需要改變一些新的思路進(jìn)行漏洞挖掘,這種方法實際是很好的能夠去挖掘本地學(xué)習(xí)提升漏洞的方法,它可以面向Windows的內(nèi)核模塊,也可以面向一些驅(qū)動程序進(jìn)行漏洞挖掘。
它的思路很簡單,一個普通用戶能夠驅(qū)動打印機(jī),就意味著一個普通用戶能夠調(diào)用打印機(jī)驅(qū)動里面的函數(shù),既然普通用戶能夠驅(qū)動我們驅(qū)動里的函數(shù),完全可以通過自己的代碼編程把這些函數(shù)剝離出來,剝離出來的目的是什么呢?就是為了進(jìn)行無序的調(diào)用,所以,我們可以有正常的順序序列,也可以有打亂順序的調(diào)用,譬如順序里的函數(shù)經(jīng)過多次調(diào)用之后看看在內(nèi)存里是不是會打架。
也可以對調(diào)用的順序看能不能改變,或者調(diào)用一些條件或參數(shù),或者沒有公開過的API函數(shù)。這也是MS10-010的特點(diǎn),它是客戶端子系統(tǒng)的漏洞,在微軟里它應(yīng)該屬于重要級的漏洞。MS10-010,也就是客戶端子系統(tǒng)主要是完成這樣的功能,它可以讓用戶登錄進(jìn)來之后開啟的每一個進(jìn)程可以在SDRSD里留下一個PLD,就是進(jìn)程列表。我們有個方法可以讓用戶退出操作系統(tǒng),他曾經(jīng)開啟過的進(jìn)程依然留在這個系統(tǒng)里,這應(yīng)該是存在安全隱患的,這和操作系統(tǒng)設(shè)計原則是違背的。
這種方式我們怎么樣讓它重現(xiàn)呢?就是打亂它的調(diào)用數(shù)據(jù),這里列出的一段代碼,我們可以改變它的邏輯條件,繞過它的安全補(bǔ)丁。我們怎么做呢?這里面每一步都可以通過安全函數(shù)實現(xiàn)。正常情況下會先連接ApiPort–退出–關(guān)閉,我們的標(biāo)志就結(jié)束了。如果打亂這個順序的調(diào)用,先連接,接著關(guān)閉,最后調(diào)用退出函數(shù),這樣它就會寄存器里變成0,進(jìn)程卻依然留在系統(tǒng)里。
基于協(xié)議握手的漏洞管理技術(shù),這也沒有什么太多的新意,主要是針對一些網(wǎng)絡(luò)軟件,這個測試空間是很大的。尤其是針對網(wǎng)絡(luò)的應(yīng)用軟件,原來我們在進(jìn)行Fuzzing測試時比較關(guān)注的是它的第一步,現(xiàn)在我們可以關(guān)注到它的第二步或第三步,我們首先可以把它整個網(wǎng)絡(luò)通信流程模擬出來,再結(jié)合我們的立項工程,立項主要用在C端(Server端),也就是說我們?nèi)ソ馕鰝鬟f過去的數(shù)據(jù)包最后在Client端或Server端是怎么解析的,我們能夠去定制更加自動化的Fuzzing測試用例,從而縮小我們測試用例的空間。
這是個典型的例子,我們往往關(guān)注的是第一步,實際往往很我多漏洞會出現(xiàn)在第二步或第三步,在連接創(chuàng)建之后或者用戶已經(jīng)登陸進(jìn)去之后,后續(xù)數(shù)據(jù)包的傳遞可能會導(dǎo)致出來一些安全漏洞,最近我們團(tuán)隊也在研究URL的漏洞,主要是針對瀏覽器和Flash的一些對象,比如SWF。一提到UAF可能大家都知道,就是User After Free。(PPT)這張圖上應(yīng)該展現(xiàn)的就是比較通用的漏洞模型,也就是說我們在解析HTML時,HTML里可以通過Create Edident去創(chuàng)建我們的對象,同時通過JS完成事件的回調(diào),事件回調(diào)中可以銷毀對象或者對對象屬性進(jìn)行修改,修改完了之后我們后面還會有繼續(xù)的引用,這樣就會導(dǎo)致UAF的漏洞。
業(yè)界也有很多Fuzz的工具,比如Grade(音)也是用開源的工具,這些工具有相應(yīng)的特點(diǎn),比如針對節(jié)點(diǎn)的,針對JS的,還有跨瀏覽器的,比如CloseFuzz針對IE、Chrome或者火狐。一般UAF漏洞,第一步,既然我們做Fuzz工具應(yīng)該怎么做?首先是創(chuàng)建我們的對象,第二步是修改創(chuàng)建對象的屬性或者進(jìn)行釋放,最后在別的地方再進(jìn)行引用,同時我們需要有一個能夠監(jiān)控到瀏覽器運(yùn)行狀態(tài)的工具,進(jìn)行Fuzzing時完全可以打開創(chuàng)建瀏覽器為子線程調(diào)試的參數(shù),這樣我們可以捕獲到當(dāng)前瀏覽器運(yùn)行的一些異常信息,最后來進(jìn)行判斷。
如果我們要實現(xiàn)一個瀏覽器的Fuzzing工具有很多資料可以進(jìn)行參考,典型的是有W3C的官方文檔,文檔里面給我們提供了大量關(guān)鍵字,可以構(gòu)造出我們的字節(jié),告訴我們dom樹的一些結(jié)構(gòu)。
W3C也提供了針對瀏覽器基本功能的測試用例,它其實有很多測試樣本,這些測試樣本對于我們寫瀏覽器Fuzzing測試工具是很有幫助的,我們可以對它進(jìn)行修改和定制。還有一些方法,例如可以利用跨引擎,大家知道,IE瀏覽器發(fā)展到今天有很多的版本,在IE8之前的都是通過JScript.dll來進(jìn)行解析的,IE9或IE9以上的版本都是通過JS和Jscript9.dll版本解析的。
這樣我們可以用早期JScript.dll來構(gòu)建我們的dom樹,用新版本來進(jìn)行解析,也就是說我們利用他們構(gòu)建方式和解析形式上的差異,看能不能夠發(fā)現(xiàn)相應(yīng)的一些漏洞。為dom樹節(jié)點(diǎn)添加事件的回調(diào)。還有一種方法,我們也可以充分地利用一個對象,這個對象也是dom樹里可能會有的一個對象,像elementRange,這個對象可以存儲dom樹當(dāng)前需要Fuzz的節(jié)點(diǎn)和應(yīng)用,在別的地方處理完之后最后再通過對象查詢它引用變化的情況,對于回調(diào)函數(shù)的構(gòu)造可能有一定的技巧,需要我們能夠有效地打亂dom的關(guān)系樹,并且它構(gòu)造的方法可能會直接影響到我們Fuzzing工具的一些效率。
最后的方法是針對Flash對象UAF的挖掘,SWF工具里S3為了提高SWF處理效率,有個新的線程跟蹤機(jī)制,存在主線程和工作線程。這里有共享內(nèi)存的特性,如果主線程和工作線程根據(jù)共享對象的處理出現(xiàn)一些不同步的現(xiàn)象就有可能出現(xiàn)UAF的漏洞,最近有一些案例,1月份出現(xiàn)2015的0311和0333,這兩個都是因為ByteArray這個對象的一些問題,也就是我們把ByteArray設(shè)成并享之后出現(xiàn)的問題。
第一個漏洞,如果說An Cooperis(音)失敗的情況下有可能會造成主線程里對它錯誤的引用;第二個是工作線程里直接對ByteArray進(jìn)行clean清楚時沒有告訴主線程,這時候我們dom memory可能導(dǎo)致一些引用,導(dǎo)致UAF漏洞,這是針對ByteArray對象的根本原因。
m-buffer是指向?qū)嶋H的對象,m-subscriber是個引用的列表,也就是說我們把ByteArray設(shè)成共享時再進(jìn)行復(fù)制,它復(fù)制了m-buffer的相關(guān)內(nèi)容,忽略了對象引用的信息,當(dāng)我們對這個新對象進(jìn)行操作時,就會使得老對象還不知道一些信息,從而在后續(xù)引用時造成UAF。
對于Flash對象,我們一般認(rèn)為,它支持三種線程之間的共享方式,只有最后一種它是以共享內(nèi)存的形式進(jìn)行同步的,也就是說第一種和第二種都是直接進(jìn)行復(fù)制,但不引用,只有第三種他們的內(nèi)存可以進(jìn)行共享和操作的。通過S3腳本設(shè)置共享對象,并對共享對象進(jìn)行處理,把它取出來使用。這是個操作的過程,也就是說我們把它取出來之后,可以寫入自己的Fuzz程序,F(xiàn)uzz程序可以對當(dāng)前這個對象進(jìn)行Clear,也可以復(fù)制成null,也可以把當(dāng)前屬性修改成位我們想要修改的屬性,后續(xù)我們再進(jìn)行進(jìn)一步引入來看看它是不是出錯,從而發(fā)現(xiàn)UAF的漏洞。
對于回調(diào)事件的設(shè)置也是很靈活的,也就是說我們可以對這個對象進(jìn)行很多處理,進(jìn)行相應(yīng)組合,最后發(fā)現(xiàn)一些漏洞。
今天這個機(jī)會很難得,后面還有點(diǎn)時間,我再把北大的小組也簡單介紹一下,我們這個團(tuán)隊在2008年時就一直存在,主要在做軟件安全方面的研究,我們主要有一個方向:立項工程,漏洞分析,漏洞挖掘,惡意代碼和安全評估。(PPT)這是我們在漏洞方面發(fā)現(xiàn)的成果,相比前面大牛們所做的工作,我們做的工作是很少的,我們給微軟提供的是3個漏洞,沒有公開的有3個漏洞。
對應(yīng)用軟件上發(fā)現(xiàn)的漏洞是本地學(xué)習(xí)提升的漏洞,主要是驅(qū)動層面發(fā)現(xiàn)的漏洞。
今天的演講就到這里!謝謝大家!