吳小王, 方 勇, 賈 鵬, 劉露平, 王 炎
(1.四川大學(xué)網(wǎng)絡(luò)空間安全學(xué)院, 成都 610065; 2. 四川大學(xué)電子信息學(xué)院, 成都 610065)
網(wǎng)絡(luò)空間是一個沒有硝煙的戰(zhàn)場,從1988年的Morris蠕蟲病毒到2017年的WannaCry勒索病毒足以可見網(wǎng)絡(luò)空間安全的嚴(yán)峻態(tài)勢. 據(jù)CNVD[1]最新的收錄漏洞類型統(tǒng)計,應(yīng)用程序漏洞占比高達(dá)58.45%,并且漏洞數(shù)量在逐年增多. 越來越多的高級持續(xù)性威脅(Advanced Persistent Threat,APT)利用應(yīng)用程序漏洞執(zhí)行破壞行為[2],對網(wǎng)絡(luò)空間安全造成巨大的威脅. 盡管各大軟件廠商在不斷改進(jìn)和完善軟件開發(fā)質(zhì)量管理,但軟件漏洞問題仍無法徹底消除.
應(yīng)用程序漏洞的利用方式多種多樣,而控制流劫持攻擊是最常見的一種. 控制流劫持攻擊允許攻擊者破壞程序的控制數(shù)據(jù),通常將執(zhí)行流重定向到攻擊者自己的注入代碼. 通過執(zhí)行惡意代碼能夠完全控制程序和系統(tǒng),造成極大的危害. 目前的操作系統(tǒng)中部署了地址空間布局隨機(jī)化(Address Space Layout Randomization,ASLR)、數(shù)據(jù)執(zhí)行保護(hù)(Data Execution Protection,DEP)、結(jié)構(gòu)化異常處理安全校驗(Safe Structured Exception Handling,SafeSEH)等安全機(jī)制,一定程度上緩解了控制流劫持攻擊對軟件和系統(tǒng)的危害. 但是,因為系統(tǒng)環(huán)境的多樣性,攻擊者仍然能夠找到繞過這些安全機(jī)制的方法. 因此,如何快速高效地發(fā)現(xiàn)攻擊威脅并及時采取應(yīng)對措施一直是學(xué)術(shù)界的研究熱點.
由Abadi等人于2005年提出的控制流完整性CFI(Control Flow Integrity)是目前防御控制流劫持攻擊的主要技術(shù)[3]. CFI的核心思想是獲取程序間接轉(zhuǎn)移指令的合法目標(biāo)并以此構(gòu)造應(yīng)用程序的控制流圖CFG(Control Flow Graph),強(qiáng)制程序在CFG的范圍內(nèi)運行,能有效地防御控制流劫持攻擊. 自提出CFI后,對控制流劫持攻擊防御的研究有很大的推進(jìn)作用,出現(xiàn)了如binCFI[4]、CCFI[5]為代表的粗粒度的CFI;為提高CFI防御能力的上下文敏感的CFI[6],基于數(shù)據(jù)約束的vCFI[7],操作系統(tǒng)內(nèi)核層面的KCoFI[8],專門針對ROP攻擊的ROPecker[9],隨機(jī)選擇特定跳轉(zhuǎn)進(jìn)行驗證的RCFI[10].
動態(tài)污點分析[11]是檢測漏洞攻擊的另一種主要技術(shù),該技術(shù)跟蹤程序數(shù)據(jù)在程序內(nèi)部的傳播,分析程序數(shù)據(jù)是否處于敏感位置,如常見的函數(shù)返回地址,從而檢測控制流劫持攻擊.
CFI策略雖然能夠有效的防御控制流劫持攻擊,但是難以在實際環(huán)境中部署. 其主要原因有兩點:(1) 是CFG的構(gòu)造困難,完整的CFG構(gòu)造需要依賴程序源碼,對于復(fù)雜的程序而言更是難以實現(xiàn). 雖然沒有源碼情況下通過逆向分析等技術(shù)也可以構(gòu)建CFG,但是對于采用了加殼[12]、混淆[13]等保護(hù)技術(shù)的二進(jìn)制程序,構(gòu)建CFG難以實現(xiàn);(2) 是需要檢查程序中的每一個間接控制轉(zhuǎn)移,細(xì)粒度的檢測會引起非常大的開銷. 此外,動態(tài)污點分析技術(shù)在實際檢測中存在過污染、欠污染等問題,所以效率較低且精度不高.
針對上述問題,本文提出了一種新的檢測控制流劫持攻擊的方法:在分析控制流劫持攻擊原理的基礎(chǔ)上,總結(jié)了控制流劫持攻擊的行為特征,然后基于二進(jìn)制插樁技術(shù),通過動態(tài)分析應(yīng)用程序的異常行為,來檢測控制流劫持攻擊. 與現(xiàn)有的動態(tài)污點分析技術(shù)和基于CFI策略的控制流劫持攻擊檢測方法相比,本文方法解決了二進(jìn)制文件分析需要依賴源碼[14]和修改二進(jìn)制文件的問題,因此具有良好的移植性;另外,所有的檢測分析僅在程序運行時進(jìn)行,不需要靜態(tài)分析和預(yù)處理的過程,具備良好的性能開銷,可以方便地部署于各種系統(tǒng)環(huán)境中.
文獻(xiàn)[15]總結(jié)了控制流劫持攻擊的基本流程(如圖1). 一個完整的控制流劫持攻擊包含以下5個步驟:構(gòu)造特定的攻擊載體;觸發(fā)并利用應(yīng)用程序中的內(nèi)存破壞漏洞;劫持程序的控制流;繞過DEP、ASLR等安全防護(hù);最后控制程序執(zhí)行流轉(zhuǎn)向惡意代碼,實現(xiàn)漏洞攻擊.
圖1 控制流劫持攻擊流程圖
2.2.1 執(zhí)行惡意代碼 執(zhí)行惡意代碼主要有代碼注入和代碼復(fù)用兩種方式. 注入的惡意代碼被稱為shellcode,一般布置到應(yīng)用程序的??臻g或者堆空間中. ??臻g用于存放函數(shù)參數(shù)的值、局部變量的值和函數(shù)調(diào)用保存的棧幀信息,正常程序不會從棧空間解析指令執(zhí)行,常見的程序漏洞如緩沖區(qū)溢出[16],則會將惡意代碼布置到??臻g中執(zhí)行. 堆是程序運行過程中動態(tài)使用的內(nèi)存空間,用于存放數(shù)據(jù),也用于存放動態(tài)生成的指令,因此應(yīng)用程序存在堆空間執(zhí)行指令的情況.
攻擊者除了利用自己構(gòu)造的惡意代碼,還有可能利用程序本身的代碼,這種利用方式稱為代碼重用技術(shù)[17],如常見的ROP[18]攻擊. ROP攻擊利用程序本身的指令片段,這些指令片段稱為gadget,每個gadget由ret指令結(jié)尾. 通過ret指令將分散的指令片段連接起來,能實現(xiàn)與shellcode相同的功能.
ASLR技術(shù)增加了ROP構(gòu)造的難度,DEP技術(shù)使得注入代碼無法執(zhí)行. 因此,代碼注入通常與代碼復(fù)用相結(jié)合,首先使用ROP關(guān)閉shellcode所在空間的數(shù)據(jù)執(zhí)行保護(hù),然后執(zhí)行shellcode.
2.2.2 造成程序異常 實際的漏洞利用過程中構(gòu)造的攻擊載體一般是針對特定的操作系統(tǒng)和目標(biāo)程序,而現(xiàn)實中的系統(tǒng)環(huán)境多種多樣,因此有不少的漏洞攻擊會因為環(huán)境不同致使應(yīng)用程序出現(xiàn)內(nèi)存訪問異常甚至崩潰的情況.
漏洞攻擊除了被動觸發(fā)程序異常,還有主動觸發(fā)異常并利用異常的情況. 當(dāng)應(yīng)用程序出現(xiàn)異常,Windows系統(tǒng)下會調(diào)用結(jié)構(gòu)化異常處理函數(shù)SEH(Structured Exception Handling,)進(jìn)行異常處理. 圖2展示了SEH鏈表結(jié)構(gòu).
圖2 SEH鏈表Fig.2 SEH chain
SEH鏈表的每一個節(jié)點都包含Next和Handler兩個成員,其中,Handler指向具體的異常處理函數(shù),Next則指向SEH鏈表的下一個節(jié)點,最后一個節(jié)點的Next指向為0xFFFFFFFF. 攻擊者可以通過觸發(fā)異常,然后覆蓋SEH鏈表中的Handler地址來劫持程序的控制流,間接地破壞了SEH鏈表的完整性.
本文通過對控制流劫持攻擊原理的研究,分析了在不同的漏洞利用攻擊情況下程序的異常行為. 提出了基于動態(tài)分析的控制流劫持攻擊檢測方法,該方法通過動態(tài)獲取程序運行時信息,針對不同的程序異常行為分別制定檢測方法.
程序的內(nèi)存空間可以分為模塊地址空間(程序加載的庫文件和可執(zhí)行程序本身)、??臻g和堆空間等3個區(qū)域. ??臻g主要存放的是函數(shù)調(diào)用時相關(guān)的信息,并不會存放代碼指令,所以若發(fā)現(xiàn)函數(shù)執(zhí)行流程跳轉(zhuǎn)到棧中,則說明存在漏洞攻擊行為. 如果不位于??臻g,則可能是位于堆空間中的惡意代碼執(zhí)行. 由于堆空間可能執(zhí)行應(yīng)用程序動態(tài)生成的代碼,因此不能直接判定為惡意代碼執(zhí)行. 但是,通常在執(zhí)行堆空間惡意代碼前會使用ROP關(guān)閉shellcode所在內(nèi)存空間的數(shù)據(jù)執(zhí)行保護(hù),因此,可以通過檢測ROP防御部分堆空間惡意代碼執(zhí)行.圖3為棧執(zhí)行檢測流程圖.
圖3 棧執(zhí)行檢測
程序執(zhí)行過程中,獲取當(dāng)前線程的棧空間范圍,如果執(zhí)行的指令地址位于??臻g范圍內(nèi),則檢測到棧執(zhí)行.
文獻(xiàn)[18]表明程序本身的一些指令片段可以構(gòu)造出圖靈完備的代碼. ROP攻擊可以利用程序本身的代碼片段執(zhí)行一些函數(shù)的功能,比如調(diào)用VirtualProtect函數(shù)改變內(nèi)存空間的可執(zhí)行權(quán)限,使得堆空間中的惡意代碼能夠執(zhí)行,或者僅僅使用ROP就完成攻擊行為. 圖4為ROP攻擊檢測流程圖.
圖4 ROP攻擊檢測Fig.4 ROP attack detection
ROP攻擊利用的指令片段稱為gadget,這些gadget一般由幾條指令組成,并以ret指令結(jié)尾,ret指令讓這些gadget聯(lián)系在一起,通過順序執(zhí)行這些gadget完成一系列功能操作.
程序正常執(zhí)行過程中函數(shù)調(diào)用與函數(shù)返回一般是匹配的,雖然存在特殊的ret指令與call指令不匹配的現(xiàn)象,但不會出現(xiàn)連續(xù)的ret與call不匹配的現(xiàn)象. 文獻(xiàn)[18]表明實際的ROP攻擊至少有17個連續(xù)的gadget,而程序正常執(zhí)行最多可能存在10個連續(xù)的gadget. 因此,為了減少誤報率和漏報率,節(jié)省時間開銷,將連續(xù)出現(xiàn)的11個ret異常識別為ROP攻擊,具體檢測流程如圖5,通過構(gòu)造影子棧,檢測到11個連續(xù)的異常ret指令,判定為ROP攻擊.
KiUserExceptionDispatcher函數(shù)是Windows系統(tǒng)下異常處理的起點,該函數(shù)有兩個參數(shù)PEXCEPTION_RECORD和PCONTEXT,分別記錄程序異常的具體信息和程序發(fā)生異常時的上下文信息. 控制流劫持攻擊中程序異常分為以下兩種情況:(1) 是攻擊失敗造成的異常;(2) 是攻擊者為了利用SEH造成的異常. 對于第二種異常情況,程序在進(jìn)行異常處理前SEH鏈表中的handler已經(jīng)被惡意數(shù)據(jù)覆蓋,導(dǎo)致SEH鏈表不再具備圖2所示的完整結(jié)構(gòu). 因此,需要在KiUserExceptionDispatcher函數(shù)被調(diào)用時獲得程序異常的具體信息和檢查SEH鏈表的完整性. SEH異常檢測流程如圖5.
圖5 SEH異常檢測Fig.5 SEH detection
當(dāng)捕獲到KiUserExceptionDispatcher函數(shù)調(diào)用時,首先判斷異常類型. 如果異常類型是“訪問無效地址”,直接判定為SEH異常; 如果不是,則接著檢查SEH鏈表的完整性,如果SEH鏈表不完整則判定為SEH異常,否則,繼續(xù)應(yīng)用程序的異常監(jiān)控.
在程序動態(tài)運行過程中,通過以上3種方法同時對程序的異常行為進(jìn)行監(jiān)控,結(jié)合程序運行時信息,實現(xiàn)對控制流劫持攻擊的檢測以及控制流劫持攻擊地址定位和類型判斷.
Pin[19]是Intel公司開發(fā)的用于動態(tài)分析的二進(jìn)制程序插樁工具,通過及時編譯技術(shù)在程序原有代碼中插入分析代碼,從而獲取程序動態(tài)運行時信息.相較于基于QEMU虛擬環(huán)境的動態(tài)分析方式,基于Pin的動態(tài)分析技術(shù)能夠直接在應(yīng)用環(huán)境中使用. 因此基于Pin工具設(shè)計了控制流劫持攻擊檢測系統(tǒng)CFHADS(Control Flow Hijacking Attack Detection System). 圖6為CFHADS系統(tǒng)架構(gòu)圖.
圖6 CFHADS系統(tǒng)架構(gòu)Fig.6 System structure of CFHADS
CFHADS主要由動態(tài)信息提取模塊和動態(tài)檢測2個模塊組成. 其中,動態(tài)信息提取模塊獲取應(yīng)用程序運行時信息以供動態(tài)檢測模塊實時分析. 使用Pin工具提供的INS_AddInstrumentFunction函數(shù)進(jìn)行指令插樁、PIN_AddThreadStartFunction函數(shù)進(jìn)行線程插樁、RTN_InsertCall函數(shù)進(jìn)行敏感API插樁. 指令插樁主要分析call指令和ret指令,并結(jié)合線程插樁,獲取應(yīng)用程序線程創(chuàng)建的相關(guān)信息為每個線程構(gòu)建影子棧;敏感API插樁主要分析程序異常處理過程中用到的函數(shù)并獲取其參數(shù). 此外,使用Pin工具提供豐富的API,可為動態(tài)檢測模塊提供應(yīng)用程序運行過程中任意時刻的上下文信息,如寄存器狀態(tài)、內(nèi)存數(shù)據(jù)等.
動態(tài)檢測模塊根據(jù)動態(tài)信息提取模塊提供的程序運行時信息,實現(xiàn)本文提出的控制流劫持攻擊檢測方法中的棧執(zhí)行檢測方法、ROP攻擊檢測方法和SEH異常檢測方法.我們通過對3種程序異常行為的檢測實現(xiàn)對控制流劫持類攻擊的檢測,檢測到攻擊的同時,保存漏洞攻擊的細(xì)節(jié),用于后續(xù)分析.
我們將用真實的漏洞攻擊樣本對系統(tǒng)的功能和性能進(jìn)行測試,表1為具體的實驗環(huán)境配置.
表1 實驗環(huán)境配置
為了驗證CFHADS系統(tǒng)的攻擊檢測效果,選取了26個真實漏洞進(jìn)行功能測試,這些漏洞都是針對的常用應(yīng)用程序,包括Microsoft office word、Microsoft office Excel、Foxit Reader、Adobe Acrobat Reader、IE等.漏洞利用樣本主要來源于exploit-db和metasploit. 具體檢測結(jié)果如表2所示.
CVE-2012-0158是針對常用軟件Microsoft office word 2007的經(jīng)典漏洞,該漏洞利用未開啟ASLR保護(hù)的msxml5.dll中跳板指令繞過DEP的安全防護(hù),使用了經(jīng)典的跳板指令jmp esp控制應(yīng)用程序在??臻g中執(zhí)行惡意代碼. 該漏洞實際的利用方式是ret-to-libc,CFHADS雖然沒有檢查ret-to-libc中最開始的異常跳轉(zhuǎn),但是準(zhǔn)確檢測到控制流劫持攻擊的后續(xù)異常行為. 表2的檢測結(jié)果顯示,EDB-ID-42918和CVE-2018-7886采用了與CVE-2012-0158相似的利用方式.
表2 真實漏洞攻擊檢測結(jié)果
CVE-2010-1797是針對PDF閱讀器Foxit Reader的漏洞攻擊,該漏洞采取了SEH利用的方式,CFHADS的檢測結(jié)果為內(nèi)存訪問異常+SEH利用+棧執(zhí)行,完整地記錄了漏洞攻擊從觸發(fā)內(nèi)存漏洞、劫持程序控制流到最后執(zhí)行惡意代碼的異常行為. 由于實際的系統(tǒng)環(huán)境與漏洞攻擊的目標(biāo)環(huán)境存在差異,因此檢測結(jié)果中以內(nèi)存訪問異常居多. CVE-2010-2883采用的攻擊方式為Heap Spray+ROP,但是漏洞利用失敗,應(yīng)用程序icucnv36.dll偏移0x2a715處訪問無效內(nèi)存地址0x0導(dǎo)致崩潰退出. 雖然漏洞攻擊沒有完整實施后續(xù)的ROP攻擊,CFHADS仍準(zhǔn)確地檢測到漏洞攻擊造成的程序異常.
實驗結(jié)果表明,CFHADS能檢測到控制流劫持攻擊各個環(huán)節(jié)的程序異常行為,雖然主要是檢測棧執(zhí)行、ROP攻擊和SEH利用,但是也間接防御了ret-to-libc、堆利用等攻擊,除了檢測到完整的控制流劫持攻擊,也能檢測到漏洞利用失敗的控制流劫持攻擊.
通過Windows系統(tǒng)下常用的5個應(yīng)用程序測試CFHADS對應(yīng)用程序的性能影響,圖7展示了應(yīng)用程序在沒有附加Pin、附加原生Pin、附加CFHADS情況下的應(yīng)用程序內(nèi)存占用情況.
從圖7可以看出,Pin的運行開銷約為原程序的3倍,而CFHADS的運行開銷約為Pin的1.2倍. 因此,相對于基于虛擬機(jī)實現(xiàn)的漏洞攻擊檢測系統(tǒng),CFHADS可以直接部署到實際應(yīng)用環(huán)境中進(jìn)行實時的控制流劫持攻擊檢測.
圖7 原程序、Pin、CFHADS內(nèi)存占用對比
本文提出了一種基于動態(tài)分析的控制流劫持攻擊檢測方法,在不依賴靜態(tài)分析或者預(yù)處理的情況下檢測應(yīng)用程序運行時的控制流劫持攻擊. 通過對控制流劫持攻擊整個流程的詳細(xì)分析,總結(jié)控制流劫持攻擊在實際環(huán)境中造成的各種異常及行為特征,識別應(yīng)用程序中的異常行為并判定為攻擊. 本文基于動態(tài)分析技術(shù)實現(xiàn)了控制流劫持攻擊檢測系統(tǒng),通過真實的漏洞攻擊檢測實驗,表明該系統(tǒng)能夠準(zhǔn)確檢測到控制流劫持攻擊,良好的運行開銷使得該系統(tǒng)能夠部署到實際的應(yīng)用環(huán)境中.
考慮到簡單的ret-to-libc難以達(dá)到攻擊目的、JOP在實際漏洞利用中實現(xiàn)困難以及直接將控制流轉(zhuǎn)移到堆空間中執(zhí)行惡意代碼實現(xiàn)復(fù)雜等情況,本文提出的方法沒有針對以上攻擊方式的具體檢測手段,因此在遇見這些情況時可能會產(chǎn)生漏報. 另外,由于Linux系統(tǒng)與Windows系統(tǒng)的一些運行機(jī)制及處理機(jī)制的不同,本文提出的方法目前只適用于Windows系統(tǒng). 后續(xù)研究計劃中將進(jìn)一步優(yōu)化檢測方法,提高控制流劫持攻擊檢測的全面性.