• 
    

    
    

      99热精品在线国产_美女午夜性视频免费_国产精品国产高清国产av_av欧美777_自拍偷自拍亚洲精品老妇_亚洲熟女精品中文字幕_www日本黄色视频网_国产精品野战在线观看

      ?

      內(nèi)存地址泄漏分析與防御

      2016-08-31 04:38:14傅建明劉秀文李鵬偉
      關(guān)鍵詞:越界指針攻擊者

      傅建明 劉秀文 湯 毅 李鵬偉

      1(空間信息安全與可信計(jì)算教育部重點(diǎn)實(shí)驗(yàn)室(武漢大學(xué)) 武漢 430072)2(武漢大學(xué)計(jì)算機(jī)學(xué)院 武漢 430072)3   (軟件工程國(guó)家重點(diǎn)實(shí)驗(yàn)室(武漢大學(xué)) 武漢 430072)

      ?

      內(nèi)存地址泄漏分析與防御

      傅建明1,2,3劉秀文1,2湯毅1,2李鵬偉1,2

      1(空間信息安全與可信計(jì)算教育部重點(diǎn)實(shí)驗(yàn)室(武漢大學(xué))武漢430072)2(武漢大學(xué)計(jì)算機(jī)學(xué)院武漢430072)3(軟件工程國(guó)家重點(diǎn)實(shí)驗(yàn)室(武漢大學(xué))武漢430072)

      (jmfu@whu.edu.cn)

      高級(jí)持續(xù)性威脅(advancedpersistentthreat,APT)攻擊通常會(huì)利用內(nèi)存地址泄漏繞過(guò)地址空間布局隨機(jī)化(addressspacelayoutrandomization,ASLR)、利用面向返回編程技術(shù)(return-orientedprogramming,ROP)繞過(guò)數(shù)據(jù)執(zhí)行保護(hù)(dataexecutionprevention,DEP).針對(duì)內(nèi)存地址泄漏漏洞,以漏洞實(shí)例為樣本,剖析了各種造成越界內(nèi)存訪問(wèn)的指針或?qū)ο蟮姆欠ú僮?,以及?cè)信道信息泄漏漏洞,并基于造成內(nèi)存泄漏的過(guò)程,給出了相應(yīng)的漏洞分類.同時(shí),從漏洞利用和攻擊的過(guò)程出發(fā),總結(jié)和歸納了內(nèi)存布局隨機(jī)化、內(nèi)存越界讀寫保護(hù)、內(nèi)存對(duì)象內(nèi)容保護(hù)、內(nèi)存對(duì)象地址隨機(jī)化等對(duì)抗內(nèi)存地址泄漏的防御方法,從而達(dá)到內(nèi)存布局看不清、內(nèi)存對(duì)象讀不到、內(nèi)存對(duì)象內(nèi)容讀不懂、關(guān)鍵內(nèi)存地址猜不準(zhǔn)的保護(hù)目的.最后,提出從程序設(shè)計(jì)角度提供對(duì)內(nèi)存布局隨機(jī)化、代碼地址隨機(jī)化、內(nèi)存對(duì)象保護(hù)等的支持,同時(shí)與操作系統(tǒng)建立協(xié)作防御機(jī)制,從而構(gòu)建縱深和立體的安全防御體系.

      APT攻擊;內(nèi)存損壞;內(nèi)存地址泄漏;地址空間布局隨機(jī)化;邊界保護(hù)

      當(dāng)訪問(wèn)的對(duì)象不同于期望的對(duì)象時(shí),會(huì)發(fā)生內(nèi)存損壞,例如對(duì)象指針越界、對(duì)象未初始化、指針指向的對(duì)象不存在等.自20世紀(jì)70年代以來(lái),內(nèi)存損壞一直是軟件的重要漏洞之一,在CERT和CVE漏洞列表中占據(jù)前列,如棧溢出、堆溢出、格式化字符串漏洞、NULL指針漏洞、整數(shù)溢出、釋放后引用漏洞[1-2]等.內(nèi)存損壞漏洞一般會(huì)導(dǎo)致拒絕服務(wù)攻擊、信息泄漏、信息竄改、控制劫持等安全威脅,攻擊者劫持控制流,使得軟件轉(zhuǎn)向攻擊者設(shè)定的代碼(Shellcode).攻擊者植入的Shellcode一般存在于?;蛘叨阎?為了阻止Shellcode獲得執(zhí)行權(quán),DEP(W∧X)技術(shù)[3]禁止棧和堆中的數(shù)據(jù)執(zhí)行.因此,代碼重用技術(shù),如ret2lib[4],ROP[5]、面向跳轉(zhuǎn)編程技術(shù)(jmp-orientedprogramming,JOP)[6]、面向調(diào)用編程技術(shù)(call-orientedprogramming,COP)[7]等,逐漸被用于Shellcode的編寫,這些技術(shù)可以繞過(guò)DEP.但這些技術(shù)的實(shí)施需要獲取重用代碼所在的內(nèi)存地址.地址空間布局隨機(jī)化(addressspacelayoutrandomization,ASLR)可使得代碼在內(nèi)存中的地址隨著模塊加載而隨機(jī)變化,從而降低Shellcode的執(zhí)行成功率.因此ASLR在Windows,Android,iOS等操作系統(tǒng)中得到了部署.如果攻擊者可以利用地址泄漏漏洞獲得重用代碼的內(nèi)存地址,則可繞過(guò)ASLR.例如,在2014年的APT攻擊事件“雪人行動(dòng)”中,攻擊者利用CVE-2014-0322漏洞,修改ActionScript腳本中vector對(duì)象的長(zhǎng)度,從而泄漏內(nèi)存地址,繞過(guò)ASLR防護(hù),最終成功實(shí)施了APT攻擊[8].因此,內(nèi)存地址泄漏成為實(shí)施內(nèi)存損壞攻擊的重要步驟.

      APT攻擊可以分為內(nèi)存地址泄漏、Shellcode注入、控制流劫持、Shellcode的執(zhí)行和木馬加載等步驟,在該攻擊的每一步驟都可以實(shí)施攻擊檢測(cè)和防御,如Shellcode的動(dòng)態(tài)檢測(cè)[9]、控制流劫持的防御[10-11].文獻(xiàn)[1]總結(jié)了內(nèi)存損壞攻擊的4種普遍類型,并列舉了其對(duì)應(yīng)的防御方法:

      1) 代碼損壞攻擊,即利用越界指針(索引)、懸掛指針等內(nèi)存漏洞達(dá)到覆寫程序代碼的目的,其防御方法是代碼完整性(codeintegrity)[12]保護(hù);

      2) 控制流劫持攻擊,即通過(guò)越界讀寫更改代碼指針,使程序跳轉(zhuǎn)到攻擊者精心構(gòu)造的Shellcode或Gadget中執(zhí)行,其防御方法是代碼指針完整性[10]保護(hù)、地址空間隨機(jī)化(ASLR)、控制流完整性(codeflowintegrity,CFI)[11]保護(hù);

      3) 只面向數(shù)據(jù)的攻擊,即惡意修改影響程序執(zhí)行的關(guān)鍵數(shù)據(jù),如分支變量等,來(lái)修改程序邏輯,其防御方法是數(shù)據(jù)完整性,數(shù)據(jù)流完整性(dataflowintegrity,DFI)[13];

      4) 信息泄漏攻擊,其防御方法數(shù)據(jù)空間隨機(jī)化(dataspacerandomization,DSR)[14]存在2進(jìn)制代碼級(jí)的兼容性問(wèn)題.文獻(xiàn)[2]按時(shí)間順序總結(jié)了內(nèi)存錯(cuò)誤的發(fā)現(xiàn)利用過(guò)程,空間內(nèi)存錯(cuò)誤的根源在于通過(guò)指針解引用實(shí)現(xiàn)越界訪問(wèn),時(shí)間內(nèi)存錯(cuò)誤的根源在于通過(guò)指針對(duì)已被釋放對(duì)象再利用.文獻(xiàn)[15]針對(duì)CC++編程語(yǔ)言中存在的代碼注入攻擊,闡述代碼補(bǔ)丁、內(nèi)存管理、動(dòng)態(tài)污點(diǎn)跟蹤、執(zhí)行路徑監(jiān)控等保護(hù)機(jī)制.

      本文聚焦在APT攻擊的內(nèi)存地址泄漏漏洞利用上,從實(shí)例出發(fā),分析和總結(jié)非法操作引發(fā)的地址越界讀寫、側(cè)信道攻擊2類地址泄漏漏洞;同時(shí),按照地址泄漏漏洞的攻擊流程,從內(nèi)存布局推測(cè)、內(nèi)存越界讀寫、讀取對(duì)象內(nèi)容、關(guān)鍵地址信息獲取4個(gè)階段分析和討論內(nèi)存地址泄漏的檢測(cè)和防御.本文的工作有利于較全面解釋地址泄漏漏洞的本質(zhì),為降低內(nèi)存信息泄漏帶來(lái)的危害提供支持,從攻擊源頭阻止或者抑制APT攻擊.

      1 內(nèi)存地址泄漏的基本模型

      Shellcode是攻擊者向目標(biāo)進(jìn)程注入的攻擊代碼.一般情況下,Shellcode尺寸約幾百字節(jié),其功能包括環(huán)境的探測(cè)、去DEP、自解密、代碼重定位、獲取系統(tǒng)API地址、下載并運(yùn)行(或加載)可執(zhí)行模塊等.另外,Metasploit[16]嵌入了Shellcode的更多功能,如增加用戶、DLL注入、彈框、反向shell等.本文討論的Shellcode由各種重用代碼的地址鏈構(gòu)成,表1為一個(gè)簡(jiǎn)單的Shellcode,該Shellcode略去了數(shù)據(jù)部分,僅由kernel32.dll中代碼對(duì)應(yīng)的地址構(gòu)成,表示創(chuàng)建一個(gè)計(jì)算器的進(jìn)程.如果該Shellcode位于堆中,則需要增加修改ESP的指令(例如movesp,eax).

      設(shè)Shellcode={a1,a2,…,an},其中ai(1≤i≤n)表示某重用代碼的地址.表1中的Shellcode表示為{0x7c83ed85,0x7c9228cb,0x7c83ed85,0x7c96e68f,0x7c86114d,0x7c80e0bf,0x7c81caa2,0x7c9478e4},這里假設(shè)kernel32.dll的基址為0x7c800000.如果kernel32.dll加載時(shí)其加載的基址隨機(jī)化為0x77b70000,則表1的Shellcode無(wú)法執(zhí)行,因?yàn)?x7c83ed85對(duì)應(yīng)的指令不是“Ret”.

      Table 1 ROP-based Shellcode表1 基于ROP的Shellcode

      內(nèi)存泄漏攻擊假設(shè)在?;蛘叨阎杏幸粋€(gè)指針變量vp,例如數(shù)據(jù)指針或者函數(shù)指針,vp指向與Shellcode關(guān)聯(lián)的模塊中某個(gè)固定地址Org_ma.Org_ma表示沒(méi)有隨機(jī)化的內(nèi)存地址值.當(dāng)該模塊的加載地址隨機(jī)化后,Org_ma的值變?yōu)锳slr_ma.

      內(nèi)存地址泄漏是指攻擊者利用漏洞探測(cè)到vp的值A(chǔ)slr_ma.vp隨模塊隨機(jī)化加載前后的基址偏移量Image_offset=Aslr_ma-Org_ma.當(dāng)前廣泛部署的ASLR機(jī)制只會(huì)對(duì)各可執(zhí)行模塊的加載基址進(jìn)行隨機(jī)化處理,模塊內(nèi)部的代碼和數(shù)據(jù)結(jié)構(gòu)的布局相對(duì)固定.攻擊者一旦窺知指針變量vp的值A(chǔ)slr_ma,根據(jù)基址偏移量,可以計(jì)算出vp所在模塊內(nèi)的各指令序列的加載基址.表1中的所有地址加上Image_offset后就可以正常執(zhí)行.因此,內(nèi)存地址泄漏攻擊就是泄漏指向模塊空間的指針vp的值,Value(vp)=Aslr_ma.

      2 內(nèi)存地址泄漏漏洞

      內(nèi)存地址泄漏的本質(zhì)是讀取特定地址的指針數(shù)據(jù),然后利用該數(shù)據(jù)獲得代碼的內(nèi)存地址.圖1從主動(dòng)探測(cè)——地址越界讀寫、被動(dòng)偵聽(tīng)——側(cè)信道攻擊2個(gè)角度介紹內(nèi)存地址泄漏攻擊.地址越界讀寫不僅僅是內(nèi)存空間上的地址越界訪問(wèn),更包含邏輯上的越界讀寫,即在程序的正常執(zhí)行流中,某個(gè)內(nèi)存區(qū)域或者寄存器在程序邏輯的角度上是不應(yīng)該被訪問(wèn)的或者是攻擊者沒(méi)有權(quán)限訪問(wèn)的.側(cè)信道攻擊作為一種通過(guò)度量開(kāi)銷信息來(lái)間接窺探隱藏信息的攻擊方式,與主流的攻擊方式有很大不同.我們無(wú)法把側(cè)信道信息與攻擊者完全隔離,攻擊者也無(wú)法從開(kāi)銷信息里推測(cè)出完全準(zhǔn)確的地址信息.

      Fig. 1 Classification of memory address leakage vulnerabilities.圖1 內(nèi)存地址泄漏漏洞的分類

      內(nèi)存越界讀寫漏洞源于對(duì)指針或?qū)ο蟮姆欠ú僮?根據(jù)非法操作能否使被攻擊對(duì)象本身存在可被利用的脆弱點(diǎn),把針對(duì)指針或?qū)ο蟮姆欠ú僮鞣譃?類:對(duì)象的脆弱屬性和函數(shù)的惡意利用.對(duì)象的脆弱屬性細(xì)分為:對(duì)象生命周期管理不規(guī)范、對(duì)象類型屬性轉(zhuǎn)換不安全、對(duì)象長(zhǎng)度屬性修改不合理,這類漏洞的直接后果是改變被攻擊對(duì)象的某類脆弱屬性,使攻擊者可以利用該脆弱屬性達(dá)到越界訪問(wèn)的目的;而函數(shù)的惡意利用細(xì)分為:內(nèi)存操作函數(shù)的惡意利用、格式化函數(shù)的惡意利用,這類漏洞作用的被攻擊對(duì)象本身不存在不合理的脆弱點(diǎn),攻擊者通過(guò)對(duì)這2類函數(shù)的惡意利用產(chǎn)生越界復(fù)制及內(nèi)存敏感信息泄漏等后果.

      2.1對(duì)象的脆弱屬性

      對(duì)象的脆弱屬性主要包括由釋放后再引用(useafterfree,UAF)漏洞引起的對(duì)象生命周期管理不規(guī)范,由基本類型混淆、復(fù)雜類型混淆漏洞造成的對(duì)象類型屬性轉(zhuǎn)換不安全,由整數(shù)溢出漏洞、修改特定數(shù)據(jù)結(jié)構(gòu)的長(zhǎng)度引起的對(duì)象長(zhǎng)度屬性修改不合理這3類攻擊方式.

      2.1.1對(duì)象生命周期管理

      隨著安全防御技術(shù)的發(fā)展和部署,傳統(tǒng)的棧溢出和堆溢出漏洞的利用越來(lái)越困難.例如,Stack-Guard[17]和StackShield[18]增加了返回地址的保護(hù),HeapGuard[19]增加了Heap完整性的保護(hù),一般的棧溢出或堆溢出都會(huì)觸發(fā)這些保護(hù)機(jī)制.UAF漏洞越來(lái)越受到攻擊者的追逐,2011,2012,2013年分別有138,177,135個(gè)UAF漏洞被曝出[20].

      C++對(duì)象的創(chuàng)建和銷毀是對(duì)偶操作.對(duì)象創(chuàng)建后,會(huì)對(duì)對(duì)象中的成員變量賦值,同時(shí),該對(duì)象會(huì)被其他指針變量引用.當(dāng)對(duì)象銷毀后,對(duì)象所占的內(nèi)存被釋放.但是引用該對(duì)象的指針可能沒(méi)有被全部清空,或該對(duì)象的內(nèi)容可能沒(méi)有被清除,這樣會(huì)產(chǎn)生3個(gè)問(wèn)題:

      1) 沒(méi)有清空的指針?lè)Q為懸掛指針[21],因?yàn)樵撝羔樦赶虻膶?duì)象已經(jīng)被釋放,被釋放的內(nèi)存會(huì)被其他對(duì)象占用,則訪問(wèn)懸掛指針會(huì)產(chǎn)生不可預(yù)見(jiàn)的后果;

      2) 如果該對(duì)象釋放的空間被攻擊者控制,則攻擊者可以偽造原對(duì)象的函數(shù)指針,實(shí)現(xiàn)控制流劫持;

      3) 如果該對(duì)象釋放的空間被攻擊者控制,攻擊者可能會(huì)讀取原對(duì)象的函數(shù)指針,會(huì)出現(xiàn)信息泄漏.若該函數(shù)指針指向模塊地址,直接導(dǎo)致內(nèi)存地址泄漏.

      基于鏈表的堆塊分配和釋放機(jī)制遵循棧式管理,即對(duì)于相同大小的堆塊,新分配的堆塊可能是剛剛釋放的相同大小的堆塊.這樣,當(dāng)使用懸掛指針訪問(wèn)原堆塊所在的空間時(shí),該空間可能已被其他對(duì)象覆蓋重用,甚至是攻擊者精心構(gòu)造的惡意數(shù)據(jù).例如,漏洞CVE-2010-3971中,內(nèi)存空間的重分配導(dǎo)致引用該舊空間的寄存器被重用.該漏洞在腳本語(yǔ)言中引用CSS文件,對(duì)象CSharedStyleSheet偏移0x0d8的位置處有一指針,該指針指向CStyleSheet元素的數(shù)組.當(dāng)mshtml.dll解析到函數(shù)CShared-StyleSheet∷Notify()時(shí),會(huì)依次取出數(shù)組中的元素.當(dāng)元素內(nèi)偏移0x18處的值為1時(shí),程序會(huì)調(diào)用函數(shù)CStyleSheet∷Notify().當(dāng)發(fā)現(xiàn)包含CSS文件且CSS文件含有import命令,程序會(huì)在數(shù)組中創(chuàng)建新元素(CStyleSheet).當(dāng)元素個(gè)數(shù)大于當(dāng)前數(shù)組大小時(shí),程序會(huì)再分配CSharedStyleSheet數(shù)組內(nèi)存空間.之前數(shù)組占用的內(nèi)存空間被釋放,程序繼續(xù)執(zhí)行并返回到函數(shù)CSharedStyleSheet∷Notify()時(shí),存儲(chǔ)數(shù)組起始地址的寄存器edi仍然放著以前的內(nèi)存空間的地址,導(dǎo)致了對(duì)數(shù)組之前所占用的內(nèi)存空間的UAF漏洞.

      CVE-2014-0322利用特定的函數(shù)釋放空間,但該空間仍舊被引用.其中,攻擊者構(gòu)造一個(gè)惡意的網(wǎng)頁(yè),該網(wǎng)頁(yè)包含一個(gè)“script”元素和“select”元素.當(dāng)把“select”元素添加到“script”元素上時(shí),函數(shù)MSHTML!CElement∷Var_appendChild()被調(diào)用,CMarkup對(duì)象會(huì)被創(chuàng)建,隨后onpropertychange事件被觸發(fā).該事件處理過(guò)程中,代碼“this.outerHTML=this.outerHTML”會(huì)人為地釋放CMarkup,而CMarkup對(duì)象仍被其他變量引用.如果攻擊者構(gòu)造好數(shù)據(jù)填充到釋放的空間,則會(huì)造成嚴(yán)重的后果[22].

      在釋放對(duì)象沒(méi)有被重用的情況下,也可以利用UAF漏洞完成惡意代碼的執(zhí)行[23].

      2.1.2對(duì)象類型屬性轉(zhuǎn)換

      攻擊者對(duì)被攻擊對(duì)象的類型屬性進(jìn)行非法轉(zhuǎn)換,達(dá)到內(nèi)存越界訪問(wèn)的目的,即類型混淆漏洞.根據(jù)被攻擊對(duì)象的不同,對(duì)象類型屬性轉(zhuǎn)換細(xì)分為基本類型混淆漏洞、復(fù)雜類型混淆漏洞.基本類型是指編譯器規(guī)定的變量類型,而復(fù)雜類型則是由基本類型和復(fù)雜類型構(gòu)建的數(shù)據(jù)結(jié)構(gòu).

      1) 基本類型混淆漏洞

      不同類型的指針?biāo)笇?duì)象類型不同,當(dāng)不同類型的變量相互轉(zhuǎn)換時(shí),產(chǎn)生類型混淆漏洞.如果把指向短字節(jié)數(shù)據(jù)類型的指針強(qiáng)制轉(zhuǎn)換為指向長(zhǎng)字節(jié)數(shù)據(jù)類型的指針,則通過(guò)對(duì)該指針解引用訪問(wèn)到超過(guò)原指向?qū)ο筮吔绶秶膬?nèi)存,從而產(chǎn)生函數(shù)或者數(shù)據(jù)的指針泄漏[1].例如,把char*轉(zhuǎn)化為int*的實(shí)例時(shí),int類型在內(nèi)存中占用4B,而char類型在內(nèi)存中只占用1B,當(dāng)把指向char類型的指針強(qiáng)制轉(zhuǎn)換為指向int類型的指針,并對(duì)該指針解引用時(shí),編譯器會(huì)誤認(rèn)為其指向?qū)ο鬄閕nt類型,連續(xù)讀取4B的內(nèi)容,從而造成內(nèi)存越界訪問(wèn),產(chǎn)生地址泄漏.

      文獻(xiàn)[24]利用指針強(qiáng)制類型轉(zhuǎn)換獲得一個(gè)地址的整數(shù)值,可以利用該整數(shù)值獲得內(nèi)存地址的布局.攻擊者首先創(chuàng)建一個(gè)object,并創(chuàng)建一個(gè)指向該對(duì)象的指針thisObject.接著通過(guò)強(qiáng)制類型轉(zhuǎn)換intaddress=*(int*)thisObject;把指針thisObject指向的對(duì)象的地址值拷貝到整形變量address中.然后,攻擊者可以通過(guò)獲取特定對(duì)象的起始地址來(lái)推斷可執(zhí)行模塊的加載基址,因?yàn)槟承┛蓤?zhí)行模塊中的特定對(duì)象位置相對(duì)模塊起始地址是固定的.

      2) 復(fù)雜類型混淆漏洞

      面向?qū)ο蟪绦蛟O(shè)計(jì)語(yǔ)言,如C++和Java語(yǔ)言,可以設(shè)計(jì)各種復(fù)雜的數(shù)據(jù)結(jié)構(gòu)和數(shù)據(jù)類型.這些數(shù)據(jù)類型的相互轉(zhuǎn)換為數(shù)據(jù)訪問(wèn)提供了便利,但不恰當(dāng)?shù)霓D(zhuǎn)換會(huì)帶來(lái)安全隱患,例如類型混淆(typeconfusion)[25].

      C++提供的4種類型轉(zhuǎn)換操作符的應(yīng)用場(chǎng)合和潛在安全問(wèn)題如表2所示:

      Table 2 C++ Type Conversion表2 C++的4種類型轉(zhuǎn)換

      因?yàn)閟tatic_cast在作下行類型轉(zhuǎn)換時(shí),沒(méi)有動(dòng)態(tài)類型檢查,會(huì)引發(fā)安全問(wèn)題.同時(shí),static_cast可以實(shí)現(xiàn)把任何類型的表達(dá)式轉(zhuǎn)換成void類型,這種轉(zhuǎn)換可以繞過(guò)編譯器對(duì)指針?biāo)笇?duì)象的類型檢查,便于攻擊者實(shí)施攻擊.靜態(tài)轉(zhuǎn)換static_cast應(yīng)用在C++對(duì)象的虛表指針中會(huì)造成vtableescape[26]錯(cuò)誤.

      Fig. 2 A case of vtable escape.圖2 vtable escape實(shí)例

      圖2為vtableescape的實(shí)例,其中父類B有2個(gè)虛函數(shù),子類D有3個(gè)虛函數(shù)(其中繼承父類B的2個(gè)虛函數(shù)).指向父類B的指針被強(qiáng)制轉(zhuǎn)換(static_cast)為指向子類D,但其所指向的內(nèi)存地址范圍并沒(méi)有變化.當(dāng)強(qiáng)制引用函數(shù)h(·)時(shí),該函數(shù)指針并沒(méi)有在基類對(duì)象的虛函數(shù)表中,從而造成內(nèi)存越界操作.

      在2013年的Pwn2Own黑客大賽中,MWRLabs研究人員利用Webkit內(nèi)核的類型混淆漏洞CVE-2013-2839攻陷了Chrome[25].Webkit的內(nèi)核C++代碼實(shí)現(xiàn)了把HTML的DOM節(jié)點(diǎn)轉(zhuǎn)換為對(duì)應(yīng)標(biāo)簽對(duì)象的結(jié)構(gòu),再通過(guò)這些對(duì)象去繪制網(wǎng)頁(yè).把DOM結(jié)構(gòu)(如input,img,able等)轉(zhuǎn)換為網(wǎng)頁(yè)對(duì)應(yīng)標(biāo)簽對(duì)象的類結(jié)構(gòu)時(shí),必須滿足以下條件:1)擁有合理的標(biāo)簽名稱(如div,table,img等);2)擁有合理的命名空間或者訪問(wèn)空間.只有同時(shí)擁有合理的XMLDOM的local屬性和合理的XMLDOM的namespaceURI屬性,才可以被轉(zhuǎn)換為HTML的對(duì)應(yīng)標(biāo)簽對(duì)象的類結(jié)構(gòu).

      漏洞CVE-2013-2839是類型轉(zhuǎn)換漏洞在剪切和書簽服務(wù)中的應(yīng)用.Clipboard是一個(gè)剪切和書簽服務(wù),其實(shí)現(xiàn)代碼在處理可拖動(dòng)圖像的過(guò)程中,指定拖動(dòng)圖像被強(qiáng)制轉(zhuǎn)換為HTMLImageElement對(duì)象,該過(guò)程中沒(méi)有執(zhí)行適當(dāng)?shù)臋z查,以確保它是一個(gè)HTML圖像元素.其漏洞觸發(fā)代碼如例1所示:

      例1.Typeconfusion1.

      if(toElement(node)→hasLocalName

      (HTMLNames∷imgTag))

      clipboard→setDragImage(static_cast〈

      HTMLImageElement*〉(node));

      從例1可以看出,在對(duì)DOM節(jié)點(diǎn)進(jìn)行標(biāo)簽類型檢查時(shí),只檢查了其標(biāo)簽名稱,并沒(méi)有檢查其命名空間.這就會(huì)產(chǎn)生不合法的HTML圖像元素(比如把SVG元素轉(zhuǎn)換為HTML的對(duì)應(yīng)圖像的類結(jié)構(gòu)).而HTMLImageElement對(duì)象的虛表占用的空間比SVGElement大得多,SVG元素相鄰的存儲(chǔ)器空間被當(dāng)做HTMLImageElement虛表的一部分被占用.因此,類型混淆漏洞就造成了越界內(nèi)存的訪問(wèn).如果越界的內(nèi)存區(qū)域保存有指向模塊的指針,則該類漏洞會(huì)產(chǎn)生內(nèi)存地址泄漏.

      漏洞CVE-2013-0912同樣利用了類型混淆漏洞造成了越界內(nèi)存訪問(wèn).SVG是用XML定義的,用來(lái)描述二維矢量及矢量柵格圖形.其中,SVG文檔中的任何元素一般是SVG元素,但其擴(kuò)展性模塊ForeignObject內(nèi)可以嵌入非SVG元素.CVE-2013-0912的POC代碼在創(chuàng)建的HTML頁(yè)面中引用了SVG文件.而該SVG文件的擴(kuò)展性模塊中嵌入了一個(gè)無(wú)效元素,被Webkit解讀為HTMLUnknown-Element,即非SVG元素.通過(guò)把該非SVG元素轉(zhuǎn)換成SVG元素,造成內(nèi)存越界訪問(wèn).其對(duì)應(yīng)的觸發(fā)漏洞的Webkit內(nèi)核代碼語(yǔ)句如例2所示:

      例2.Typeconfusion2.

      if(!m_contextElement)return0;

      returnstatic_cast〈SVGElement*〉

      (m_contextElement→treeScope()→

      getElementById(m_viewTargetString));

      該SVG文件被Webkit視為DOM樹(shù),Webkit根據(jù)viewTarget屬性加載SVG文檔的view元素,相當(dāng)于根據(jù)ID屬性選擇DOM樹(shù)的節(jié)點(diǎn).從例2代碼可看出,Webkit內(nèi)核將SVG文檔中ID為m_viewTargetString的元素強(qiáng)制轉(zhuǎn)換為SVG元素.CVE-2013-0912的POC代碼通過(guò)堆噴射進(jìn)行內(nèi)存布局,HTMLUnknownElement被安插的位置緊挨著HTMLDivElement元素,當(dāng)類型混淆漏洞被觸發(fā)后,HTMLUnknownElement被視為SVG元素,SVG元素的大小為0x124B,遠(yuǎn)遠(yuǎn)大于HTMLUnknownElement的0x40B大小.攻擊者可以通過(guò)訪問(wèn)HTMLUnknownElement,越界訪問(wèn)其相鄰的HTMLDivElement元素的虛表指針.這就通過(guò)類型混淆漏洞泄漏了關(guān)鍵的內(nèi)存地址信息.

      2.1.3對(duì)象長(zhǎng)度屬性修改

      所有對(duì)象和數(shù)組都有長(zhǎng)度約束,如堆塊塊首包含長(zhǎng)度域、數(shù)組的索引下標(biāo).如果攻擊者修改數(shù)據(jù)結(jié)構(gòu)的長(zhǎng)度約束,則可以讀取給定地址的數(shù)據(jù),達(dá)到內(nèi)存地址泄漏的目的.該類漏洞包括整數(shù)溢出、修改特定數(shù)據(jù)結(jié)構(gòu)的長(zhǎng)度等.

      2014年曝出的心臟出血漏洞(CVE-2014-0160)根源在于OpenSSL密碼庫(kù)處理心跳請(qǐng)求包時(shí),對(duì)其長(zhǎng)度屬性值缺少真實(shí)性驗(yàn)證.TLS心跳包是在客戶端和服務(wù)器間定時(shí)通知對(duì)方自己狀態(tài)的一個(gè)請(qǐng)求包.TLS心跳請(qǐng)求包中包括有效載荷,payload是有效載荷的期望長(zhǎng)度.服務(wù)器把有效載荷從請(qǐng)求包復(fù)制到響應(yīng)包,忽略了對(duì)請(qǐng)求包大小的邊界檢查,即忽略了payload值的真實(shí)性.如果客戶端的有效載荷達(dá)不到payload,接收端會(huì)把請(qǐng)求包存儲(chǔ)位置之后的任意數(shù)據(jù),也當(dāng)成有效載荷裝進(jìn)響應(yīng)包里,返回給發(fā)送方,從而造成服務(wù)器的敏感信息泄漏.

      1) 整數(shù)溢出漏洞

      整數(shù)分為無(wú)符號(hào)整數(shù)(unsignedint)和有符號(hào)整數(shù)(int).當(dāng)2個(gè)整數(shù)相加或者相減時(shí),可能出現(xiàn)上溢或者下溢,得到非期望的數(shù)據(jù)[1].或者,當(dāng)把一個(gè)有符號(hào)的整數(shù)轉(zhuǎn)換為無(wú)符號(hào)整數(shù)時(shí),有可能到一個(gè)非期望的大整數(shù)[1].整數(shù)a(0xfffffff0)和整數(shù)b(0x12)相加導(dǎo)致數(shù)據(jù)上溢,得到一個(gè)比期望小很多的整數(shù)0x2,而程序仍按照期望的長(zhǎng)度(0xfffffff0)訪問(wèn)數(shù)據(jù),導(dǎo)致內(nèi)存訪問(wèn)越界.如果越界區(qū)域可以覆蓋一個(gè)部署好的函數(shù)或者數(shù)據(jù)指針,則發(fā)生內(nèi)存地址泄漏.

      CVE-2010-0010是一個(gè)整數(shù)溢出漏洞:當(dāng)Apache服務(wù)器處理Web用戶提交的分塊數(shù)據(jù)的長(zhǎng)度時(shí),忽略了整數(shù)的符號(hào)問(wèn)題,造成因整數(shù)溢出引發(fā)的堆溢出.Web用戶以分塊編碼的方式向Apache服務(wù)器提交數(shù)據(jù),數(shù)據(jù)的長(zhǎng)度是一個(gè)有符號(hào)整數(shù),服務(wù)器會(huì)為該數(shù)據(jù)分配一個(gè)緩沖區(qū).在把數(shù)據(jù)拷貝到緩沖區(qū)之前,Apache會(huì)把用戶提交的分塊編碼的長(zhǎng)度與緩沖區(qū)長(zhǎng)度進(jìn)行比較,防止拷貝數(shù)據(jù)越界.攻擊者可以把提交的數(shù)據(jù)長(zhǎng)度設(shè)定為負(fù)值,繞過(guò)該安全檢查.實(shí)際上攻擊者提交的數(shù)據(jù)長(zhǎng)度可以大于0x80000000B,造成緩沖區(qū)溢出,覆蓋相鄰位置的敏感信息(如數(shù)組索引),從而導(dǎo)致信息泄漏.

      2) 修改特定數(shù)據(jù)結(jié)構(gòu)的長(zhǎng)度

      為便于管理,堆中的數(shù)據(jù)塊由數(shù)據(jù)的長(zhǎng)度和數(shù)據(jù)內(nèi)容2部分構(gòu)成.如果攻擊者能夠覆蓋數(shù)據(jù)的長(zhǎng)度,則可以實(shí)現(xiàn)內(nèi)存越界訪問(wèn),引發(fā)信息泄漏.文獻(xiàn)[2]給出了該類攻擊,隨后操作系統(tǒng)加強(qiáng)了對(duì)堆的管理,如引入heapcookie、元數(shù)據(jù)加密等安全機(jī)制,增加了攻擊者篡改堆塊數(shù)據(jù)長(zhǎng)度的難度.

      腳本語(yǔ)言,如VBScript,JavaScript,ActionScript等,為網(wǎng)頁(yè)、文檔、媒體等提供了豐富的交互性、靈活性和可擴(kuò)展性.VBString就是一種包含長(zhǎng)度和數(shù)據(jù)內(nèi)容的結(jié)構(gòu)類型,CVE-2012-1876漏洞就是攻擊該數(shù)據(jù)結(jié)構(gòu)的長(zhǎng)度域,越界訪問(wèn)指向模塊的指針.該漏洞的原理在于可以實(shí)現(xiàn)一個(gè)任意地址的任意寫漏洞.例3為該漏洞的一個(gè)示例:

      例3.Arbitraryaddresswrittenvulnerability.

      〈tablestyle=“table-layout:fixed”〉

      〈colid =“132” width=“41” span=“1”〉

       〈col〉〈table〉

      〈script〉

      functionover_trigger() {

      var obj_col = document.getElementById

      (“132”);

      obj_col.width=“42765”;

      obj_col.span = 1000;

      }

      setTimeout(“over_trigger();”,15000);

      例3首先生成一個(gè)id =“132”的CTablelayout對(duì)象,利用width和span的值改寫對(duì)象的內(nèi)存,其中width控制改寫的值,span控制改寫的地址及改寫值的寫入次數(shù).隨后執(zhí)行函數(shù)over_trigger(),由于沒(méi)有把新引入的span值保存,則寫入內(nèi)存空間的大小不變,而寫入次數(shù)變?yōu)? 000,導(dǎo)致寫入空間后緊鄰的內(nèi)存空間被改寫.攻擊者控制好width和span的值,在寫入空間后面部署VBString,就可以改寫VBString的長(zhǎng)度域.如果CButtonLayout對(duì)象被部署在VBString之后,因?yàn)閂BString的訪問(wèn)空間變大,就可以讀取CButtonLayout對(duì)象的虛表指針.由于該指針指向mshtml.dll中的固定偏移量,攻擊者可由該指針值推測(cè)mashtml.dll的加載基址.

      CVE-2014-0322在產(chǎn)生UAF漏洞后,結(jié)合ActionScript3.0的vector屬性,可以實(shí)現(xiàn)任意地址的數(shù)值加1的操作.vector 是一種經(jīng)常使用的數(shù)據(jù)結(jié)構(gòu),包含一個(gè)8B的頭部,其中前4B表示 vector的長(zhǎng)度字段size.頭部后為存儲(chǔ)數(shù)據(jù)的空間,數(shù)據(jù)元素個(gè)數(shù)由size決定,每個(gè)元素大小為4B.如果V1和V2是連續(xù)存放的vector,如(eax+10h)指向V1.size,則執(zhí)行incdwordptr[eax+10h]后,V1.size為0x03ff.隨后利用ActionScript的腳本直接修改V2.size=V1[0x03fe]=N.N為足夠大的正整數(shù),如0x7fffffff,利用V2[x]就可以訪問(wèn)V2后的任意地址空間.

      Fig. 3 The length field of vector modification in    CVE-2014-0322.圖3 利用CVE-2014-0322修改vector長(zhǎng)度

      包含長(zhǎng)度屬性的數(shù)據(jù)結(jié)構(gòu)還有ArrayBuffer,Array,Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,DataView等.攻擊者通過(guò)修改這些特定數(shù)據(jù)結(jié)構(gòu)的長(zhǎng)度字段實(shí)現(xiàn)任意地址的讀寫.

      2.2函數(shù)的惡意利用

      對(duì)于不存在敏感屬性被攻擊者利用的被攻擊對(duì)象,惡意利用內(nèi)存操作函數(shù)(sprintf,strcpy,strncpy, strncat,memcpy,memset等)會(huì)導(dǎo)致越界復(fù)制數(shù)據(jù);惡意利用格式化函數(shù)(fprintf,printf,sprintf,snprintf,vfprintf)則會(huì)偷窺棧內(nèi)敏感信息,最終引發(fā)函數(shù)或者數(shù)據(jù)指針的泄漏[27].

      2.2.1內(nèi)存操作函數(shù)的惡意利用

      文獻(xiàn)[28]給出了一個(gè)覆蓋鄰接內(nèi)存變量,產(chǎn)生信息泄漏或數(shù)據(jù)改寫的實(shí)例.該實(shí)例類似于數(shù)組賦值中常見(jiàn)的off-by-one漏洞.strncpy(·)只按照給定長(zhǎng)度拷貝的字符串,拷貝后不會(huì)自動(dòng)添加NULL.該實(shí)例中,客戶端要與服務(wù)器端建立起聯(lián)系,必須先提交其用戶名和密碼.服務(wù)器把客戶端發(fā)來(lái)的用戶名存儲(chǔ)在數(shù)組buff中,用strncpy(·)將其拷貝到user[100]中.如果數(shù)組buff中的字符串大于等于100B,user[100]中不存在NULL結(jié)束符.但在調(diào)用函數(shù)snprintf(·)的過(guò)程中,程序會(huì)從數(shù)組user的源地址開(kāi)始以指定格式復(fù)制字符串到數(shù)組buff中,直到遇到NULL結(jié)束符為止.這樣會(huì)泄漏securitycookie、前棧幀ebp、返回地址等堆棧敏感信息.

      CVE-2007-3410漏洞就是利用函數(shù)strncpy造成棧緩沖區(qū)溢出,導(dǎo)致了任意指令的執(zhí)行.該漏洞存在于RealPlayerHelixPlayer播放器的墻壁時(shí)鐘(wallclock),該功能在處理hh:mm:ss:ff時(shí)間格式時(shí),忽略了strncpy(buf,pos,len)代碼中buf緩沖區(qū)的常數(shù)長(zhǎng)度.攻擊者對(duì)該漏洞造成的棧溢出加以利用,會(huì)泄漏棧內(nèi)的敏感信息.

      2.2.2格式化函數(shù)的惡意利用(formatstring)

      常見(jiàn)的格式化函數(shù)有fprintf,printf,sprintf,snprintf,vfprintf,vprintf,vsprintf,vsnprintf等.這些格式化函數(shù)可以把變量?jī)?nèi)容按照指定的格式輸出到給定的緩沖區(qū).如果攻擊者可以控制格式化函數(shù)中的輸出格式、輸入的地址、輸出的緩沖區(qū),則會(huì)造成嚴(yán)重的格式化漏洞.格式化字符串漏洞就是指攻擊者可以控制輸出格式,即在調(diào)用格式化的輸出函數(shù)時(shí),沒(méi)有指定要輸出的字符串的輸出格式.這樣,函數(shù)就會(huì)在要逐字打印的字符串中尋找特殊的格式字符.

      如果要輸出打印的字符包含“%n”,則能寫任意值到攻擊者選定的內(nèi)存中.因?yàn)楦袷揭?guī)定符“%n”把前面已經(jīng)打印的字符長(zhǎng)度寫入其對(duì)應(yīng)的實(shí)參變量中.該攻擊利用巧妙的布局,可以實(shí)現(xiàn)修改程序的返回地址,進(jìn)而取得程序的控制權(quán).該輸出格式在目前的編譯器中被缺省關(guān)閉[29].

      如果要輸出的字符串為“%x%x%x%x%x%x%x%x”或“%p%p%p%p%p%p%p%p”[30],但輸出函數(shù)并沒(méi)有指定其輸出的的格式規(guī)定符.攻擊者可以利用這點(diǎn)窺知堆棧中的內(nèi)容并以16進(jìn)制的形式輸出.文獻(xiàn)[31]給出了利用格式化字符串漏洞來(lái)偷窺程序內(nèi)容,甚至關(guān)鍵函數(shù)的返回地址的方法.

      2.3側(cè)信道攻擊

      側(cè)信道攻擊利用側(cè)信道信息(如時(shí)間開(kāi)銷、空間開(kāi)銷或者功耗開(kāi)銷)推測(cè)出對(duì)攻擊者有用的信息,如加密的密鑰、安全保護(hù)措施或者內(nèi)存地址信息等.

      內(nèi)核空間ASLR能有效阻礙對(duì)操作系統(tǒng)內(nèi)核或驅(qū)動(dòng)程序的本地攻擊.文獻(xiàn)[32]通過(guò)針對(duì)內(nèi)存管理系統(tǒng)的通用的側(cè)信道攻擊方法,突破了ASLR保護(hù)機(jī)制的限制,推斷出程序的地址空間布局.文獻(xiàn)[32]中列舉了3種方法:高速緩存探查(cacheprobing)、檢測(cè)發(fā)生2次頁(yè)錯(cuò)誤的時(shí)間差(doublepagefault,DPF)、預(yù)加載地址轉(zhuǎn)換緩存(addresstranslationcachepreloading),這些突破內(nèi)核ASLR的方法能定位內(nèi)核空間到頁(yè)的粒度.一個(gè)用戶模式的應(yīng)用程序不能直接訪問(wèn)內(nèi)核空間,每次在用戶模式下嘗試訪問(wèn)內(nèi)核空間內(nèi)存時(shí)會(huì)導(dǎo)致一個(gè)訪問(wèn)沖突. 以DPF為例,從用戶模式訪問(wèn)內(nèi)存頁(yè)p,會(huì)導(dǎo)致頁(yè)錯(cuò)誤并傳遞到進(jìn)程的異常處理.如果p被加載過(guò),即p是已經(jīng)分配物理內(nèi)存的頁(yè)面,第1次從用戶模式訪問(wèn)p時(shí),旁路轉(zhuǎn)換緩沖(translationlookasidebuffer,TLB)會(huì)緩存該頁(yè),因此在第2次訪問(wèn)頁(yè)面p時(shí),頁(yè)錯(cuò)誤的傳遞時(shí)間會(huì)相對(duì)較短.如果p沒(méi)有被加載過(guò),則不會(huì)被TLB緩存,2次頁(yè)錯(cuò)誤的傳遞時(shí)間無(wú)明顯差別,所以可以根據(jù)頁(yè)錯(cuò)誤的傳遞時(shí)間估計(jì)該頁(yè)面是否加載過(guò).DPF方法對(duì)內(nèi)核空間的頁(yè)面分配和驅(qū)動(dòng)程序的映射給出一個(gè)大致的估計(jì),可以定位到頁(yè)面的范圍,但準(zhǔn)確定位一個(gè)驅(qū)動(dòng)程序的基址還是比較困難的.

      模塊級(jí)地址隨機(jī)化如ASLR、指令級(jí)地址隨機(jī)化(instructionlocationrandomization,ILR)[33]、基本指令塊(連續(xù)的指令序列)地址隨機(jī)化(self-trans-forminginstructionrelocation,STIR)[34],在代碼中隨機(jī)加入NOP指令模糊Gadget定位如librando[35],這些代碼多樣化技術(shù)混淆了執(zhí)行代碼的內(nèi)存布局,但文獻(xiàn)[36]提出的故障分析攻擊及計(jì)時(shí)側(cè)信道攻擊在利用內(nèi)存損壞攻擊越界覆寫后,能識(shí)別多樣化代碼中的部分NOP指令,Gadget甚至函數(shù)的布局.故障分析攻擊比如攻擊者覆寫數(shù)據(jù)指針?biāo)饕?,并指向代碼段,如果指針解引用值為0x00,攻擊者則收到報(bào)錯(cuò)信息.借此定位字節(jié)0x00,而0x00一般分布在代碼段的常量中,甚至可作為定位Gadget或者函數(shù)的明顯特征.同樣改寫數(shù)據(jù)指針?biāo)饕?,在?jì)時(shí)攻擊中,攻擊者通過(guò)構(gòu)造不同輸入,來(lái)猜測(cè)其指向的棧中關(guān)鍵地址值.如下列分支:

      1)if(ptr[index] % input==0)

      2) i=i×2;

      3)else

      4) i=i+2.

      分支2)明顯比分支4)執(zhí)行時(shí)間長(zhǎng),借此推斷輸入值與修改后的指針解引用值(如返回地址)的關(guān)系.但故障分析攻擊及計(jì)時(shí)攻擊泄漏的信息很大程度上依賴于攻擊者構(gòu)造值與其收到回應(yīng)之間映射關(guān)系的唯一性,且可利用內(nèi)存損壞漏洞造成的指針覆寫須直接影響控制流.

      3 內(nèi)存地址泄漏的防御

      內(nèi)存損壞攻擊主要包含4個(gè)步驟:

      1) 內(nèi)存布局推測(cè).不管是注入代碼攻擊,還是ROP,JOP,COP等代碼重用攻擊,攻擊者成功攻擊的前提條件是能夠推測(cè)出被攻擊對(duì)象的內(nèi)存布局.如果攻擊者無(wú)法預(yù)知被攻擊對(duì)象(如函數(shù)指針、虛表指針、函數(shù)返回地址、可重用指令序列等)的相關(guān)地址信息,則無(wú)法達(dá)到劫持啊程序控制流,執(zhí)行惡意代碼的目的.

      Fig. 4 Steps and defensive approach of memory corruption attack.圖4 內(nèi)存損壞攻擊的步驟及防御方法

      2) 內(nèi)存越界讀寫.在攻擊者事先獲知被攻擊對(duì)象的內(nèi)存地址信息的情況下,攻擊者可以控制的進(jìn)程對(duì)象(如與外部輸入相關(guān)的數(shù)組等)與被攻擊對(duì)象在內(nèi)存布局上還存在一定差距,攻擊者無(wú)法直接訪問(wèn)這些被攻擊對(duì)象的信息,只能利用第2節(jié)的漏洞達(dá)到越界讀寫的目的.

      3) 讀取對(duì)象內(nèi)容.如果攻擊者達(dá)到越界讀寫甚至訪問(wèn)整個(gè)進(jìn)程內(nèi)存空間的目的,防御方則需要對(duì)被攻擊對(duì)象的內(nèi)容進(jìn)行加密.這樣,攻擊者越界訪問(wèn)到的敏感信息只是加密后的信息,無(wú)法獲取真實(shí)值.

      4) 關(guān)鍵地址信息獲取.在攻擊者已經(jīng)成功獲取泄漏點(diǎn)——被攻擊對(duì)象的真實(shí)信息(可執(zhí)行模塊中的函數(shù)指針、數(shù)據(jù)指針、虛表指針)的情況下,執(zhí)行惡意代碼還需要攻擊者獲取其他關(guān)鍵的地址信息,比如可重用代碼的實(shí)際地址.

      防御方在攻擊者已經(jīng)成功獲取切入點(diǎn)的情況下,仍然可以通過(guò)設(shè)置代碼頁(yè)不可讀權(quán)限阻止大規(guī)模的讀代碼行為,或者通過(guò)細(xì)粒度的地址空間隨機(jī)化技術(shù)妨礙其窺知攻擊成功所需的其他敏感信息,大大降低內(nèi)存損壞攻擊的成功率.如果攻擊者突破了以上4層防護(hù),已獲取實(shí)施攻擊所需的地址信息,構(gòu)造攻擊所重用的Gadget,實(shí)施代碼重用攻擊.

      如圖4所示,針對(duì)內(nèi)存損壞攻擊的4個(gè)步驟,主要有如下防御方法:1)對(duì)被攻擊對(duì)象的相關(guān)內(nèi)存布局進(jìn)行隨機(jī)化處理,增大攻擊者猜測(cè)被攻擊對(duì)象地址信息的難度;2)對(duì)被攻擊對(duì)象提供邊界保護(hù),防止攻擊者越界訪問(wèn)敏感信息;3)對(duì)被攻擊對(duì)象內(nèi)容的真實(shí)值進(jìn)行加密,混淆攻擊者獲取的敏感信息;4)設(shè)置代碼頁(yè)不可讀屬性或部署細(xì)粒度的地址空間隨機(jī)化技術(shù),降低切入點(diǎn)泄漏帶來(lái)的影響.即使面對(duì)潛在的代碼重用攻擊,可以從檢測(cè)Gadget鏈,控制流完整性2個(gè)方面及時(shí)檢測(cè)甚至阻止攻擊.

      本節(jié)的防御方法為內(nèi)存敏感信息(如進(jìn)程對(duì)象的內(nèi)存基址、指令序列的內(nèi)存基址等)、虛表指針、數(shù)據(jù)指針、代碼指針、由指針(索引)訪問(wèn)的對(duì)象、棧內(nèi)的敏感信息等被攻擊對(duì)象提供保護(hù).

      3.1內(nèi)存布局隨機(jī)化

      攻擊者成功實(shí)施攻擊的前提是猜測(cè)出被攻擊對(duì)象的內(nèi)存布局,比如函數(shù)指針或函數(shù)返回地址在棧內(nèi)存的布局是遵循一定規(guī)則排列的,攻擊者可以根據(jù)先驗(yàn)知識(shí),利用與被攻擊對(duì)象相鄰的數(shù)組或緩沖區(qū),間接修改函數(shù)指針或返回地址,成功實(shí)施攻擊.如果在棧內(nèi)存、堆內(nèi)存、靜態(tài)緩沖區(qū)中的進(jìn)程對(duì)象分布不可預(yù)知,則攻擊者無(wú)法獲知被攻擊對(duì)象的相關(guān)內(nèi)存布局,也無(wú)法成功發(fā)起攻擊.本節(jié)分別從棧內(nèi)存、堆內(nèi)存的內(nèi)存布局隨機(jī)化和結(jié)構(gòu)體內(nèi)部布局隨機(jī)化混淆內(nèi)存布局.

      3.1.1棧內(nèi)存布局隨機(jī)化

      攻擊者利用基本棧的緩沖區(qū)溢出打破棧內(nèi)對(duì)象邊界,越界讀取敏感信息,甚至篡改控制數(shù)據(jù).而傳統(tǒng)的調(diào)用棧規(guī)則為棧幀及棧內(nèi)對(duì)象的分布提供了可預(yù)測(cè)性,使棧內(nèi)對(duì)象UAF及未初始化讀取錯(cuò)誤成為可能.

      文獻(xiàn)[37]提出的基于棧的內(nèi)存錯(cuò)誤保護(hù)——StackArmor——有效混淆了棧內(nèi)存布局.Stack-Armor提供的隨機(jī)棧幀分配器為每個(gè)線程調(diào)用棧維持多個(gè)連續(xù)的、由不被映射的PageGuard頁(yè)環(huán)繞的物理?xiàng)?,并在虛擬地址空間中為邏輯棧幀預(yù)定對(duì)應(yīng)的映射項(xiàng),而映射項(xiàng)對(duì)應(yīng)的物理?xiàng)蛄须S機(jī).這樣,邏輯上相鄰的棧幀其物理分布不可預(yù)測(cè).同時(shí),該分配器在設(shè)置新棧幀時(shí),會(huì)把剛釋放的棧幀映射項(xiàng)與其他任意一個(gè)映射項(xiàng)交換,提高了棧幀分配選擇的隨機(jī)性.StackArmor通過(guò)2進(jìn)制級(jí)插樁調(diào)用該分配器為靜態(tài)分析時(shí)篩選出的棧幀及緩沖區(qū)提供保護(hù).涉及到局部變量指針計(jì)算的函數(shù)棧幀,是潛在的被攻擊對(duì)象,程序在該函數(shù)調(diào)用點(diǎn)為其隨機(jī)分配并切換到新棧幀,并在調(diào)用結(jié)束后返回到原始堆棧繼續(xù)執(zhí)行.作為攻擊者的可控棧內(nèi)對(duì)象,如果某個(gè)緩沖區(qū)的所有引用不用作訪問(wèn)其他內(nèi)存對(duì)象,則可將其獨(dú)立放置到隨機(jī)分配的新棧幀中.被隔離的函數(shù)棧幀和緩沖區(qū)使越界讀寫完全失效.StackArmor結(jié)合了靜態(tài)分析和插樁的策略,在利用新棧幀隔離可控對(duì)象及被攻擊對(duì)象的基礎(chǔ)上,隨機(jī)化處理新棧幀的分配布局,攻擊者無(wú)法通過(guò)棧內(nèi)可控對(duì)象推測(cè)被攻擊對(duì)象的布局.

      3.1.2堆內(nèi)存布局隨機(jī)化

      基于鏈表的堆塊分配和釋放機(jī)制是遵循棧式管理的,攻擊者可以利用該特性明確內(nèi)存布局,這為通過(guò)越界內(nèi)存訪問(wèn)獲取敏感地址信息提供了很大便利.

      在CVE-2012-1876漏洞利用中,攻擊者首先通過(guò)腳本申請(qǐng)16個(gè)Button對(duì)象,每個(gè)Button對(duì)象大小為0x100,同時(shí)設(shè)置每個(gè)Button對(duì)象的ClassName,Title(長(zhǎng)度均為0x100的字符串對(duì)象).接著釋放掉16個(gè)ClassName占用的0x100大小的空間,這樣將會(huì)在剛申請(qǐng)的內(nèi)存空間上留下16個(gè)“小孔”.然后,攻擊者申請(qǐng)0x100大小的Spanstructure,希望Spanstructure落在16個(gè)小孔中的一個(gè).繼續(xù)釋放Button對(duì)象的Title,同時(shí)大量申請(qǐng)長(zhǎng)度為0x100的VBString,將剛釋放掉的堆空間填充.最后,利用該漏洞修改VBString的長(zhǎng)度,實(shí)現(xiàn)對(duì)給定地址的讀操作,達(dá)到內(nèi)存信息(地址)泄漏的目的.

      在遵循棧式管理的內(nèi)存分配機(jī)制下,攻擊者利用UAF及2次釋放漏洞精確控制被攻擊對(duì)象相鄰的內(nèi)存布局.針對(duì)UAF漏洞根源——懸掛指針解引用,Undangle[38]和FreeSentry[39]在程序運(yùn)行時(shí)插入動(dòng)態(tài)檢查,起到一定程度的防御作用.Undangle[38]利用動(dòng)態(tài)污點(diǎn)分析工具跟蹤程序在指定輸入下的執(zhí)行軌跡,其核心EarlyDetection技術(shù)從執(zhí)行軌跡中識(shí)別懸掛指針的創(chuàng)建點(diǎn),跟蹤懸掛指針在執(zhí)行流中的傳播,直到再次使用該懸掛指針,從而及時(shí)檢測(cè)出UAF及2次釋放漏洞.FreeSentry對(duì)指針創(chuàng)建及指針指向?qū)ο笮薷牟僮鞑迦胱远x的函數(shù)regptr(),記錄指針地址,引用對(duì)象的邊界等信息,當(dāng)捕獲到釋放內(nèi)存函數(shù)時(shí),將引用對(duì)應(yīng)內(nèi)存塊的所有懸掛指針指向無(wú)效內(nèi)存地址.FreeSentry可擴(kuò)展為邊界檢查.而DANGNULL[40]則在LLVM的中間代碼級(jí)進(jìn)行靜態(tài)插樁,識(shí)別指針?lè)峙洳僮鞑⒉迦胲壽E函數(shù),在運(yùn)行時(shí)建立指針和內(nèi)存對(duì)象之間的引用關(guān)系,并追蹤堆內(nèi)存分配、釋放函數(shù),及時(shí)發(fā)現(xiàn)懸掛指針并使其失效,從根本上阻止懸掛指針解引用,但廢棄不被解引用的良性懸掛指針會(huì)帶來(lái)額外開(kāi)銷.

      如果增加相同大小的堆塊在內(nèi)存分布的隨機(jī)性,突破棧式管理中內(nèi)存分配釋放的特性,那么攻擊者部署2個(gè)鄰接對(duì)象,精確對(duì)象的內(nèi)存布局的難度就會(huì)大大增加.文獻(xiàn)[41]中提出了一種基于虛擬簇的堆塊分配機(jī)制.每次分配大小為A的對(duì)象時(shí),從虛擬簇中大小為A的堆塊和2倍大小為A的堆塊中分配一塊.因此,該機(jī)制擴(kuò)大堆塊待分配的空間和打亂分配順序,以此提高堆塊分配的隨機(jī)性,降低釋放后被分配的概率.這樣,攻擊者越界訪問(wèn)的對(duì)象并不可控.DieHard[42]是隨機(jī)化的內(nèi)存管理器,應(yīng)用程序?qū)?yīng)的堆空間大小是其所需最大空間的M倍(M≥2).程序所請(qǐng)求堆塊對(duì)應(yīng)的堆區(qū)域(相同大小的堆塊區(qū)域)只允許至多填滿1M的空間,且剛剛釋放的堆塊與同堆區(qū)域內(nèi)的空閑堆塊有相同概率被下次分配操作選中.DieHarder[43]的分散頁(yè)布局參考了OpenBSD的內(nèi)存分配機(jī)制,利用系統(tǒng)調(diào)用mmap()實(shí)現(xiàn)進(jìn)程對(duì)象到內(nèi)存之間的分散頁(yè)映射,即內(nèi)存頁(yè)面不連續(xù).分散頁(yè)之間的空隙是未被映射的內(nèi)存,該內(nèi)存作為PageGuard預(yù)防內(nèi)存的越界訪問(wèn).

      上述內(nèi)存分配的隨機(jī)化增加了內(nèi)存布局的不確定性.當(dāng)然,該隨機(jī)化需要修改內(nèi)存的分配機(jī)制,增加了空閑的內(nèi)存空間,同時(shí)也增加了內(nèi)存分配的開(kāi)銷.

      3.1.3結(jié)構(gòu)體內(nèi)部布局隨機(jī)化

      結(jié)構(gòu)體是攻擊者劫持程序執(zhí)行流的主要利用目標(biāo).在緩沖區(qū)溢出漏洞中,攻擊者通過(guò)越界覆寫棧中與用戶輸入相關(guān)的數(shù)組,修改函數(shù)的返回地址.在包含有函數(shù)指針的結(jié)構(gòu)體中,攻擊者控制與函數(shù)指針相鄰的外部輸入變量,篡改函數(shù)指針.

      文獻(xiàn)[44]中提出的基于封裝結(jié)構(gòu)的隨機(jī)化方法在一定程度上緩解了上述攻擊過(guò)程.這種隨機(jī)化方法利用了編譯器GCC,在源程序中的函數(shù)、結(jié)構(gòu)體以及類這些數(shù)據(jù)結(jié)構(gòu)的抽象語(yǔ)法樹(shù)(AST)生成以后,隨機(jī)更改其內(nèi)部數(shù)據(jù)成員的鏈表串接順序.隨機(jī)化策略是:1)在靠近被攻擊對(duì)象(函數(shù)返回地址及函數(shù)指針)的相對(duì)低地址處布置“哨兵”(Guard區(qū)域);2)在與用戶輸入相關(guān)的數(shù)組之間布置“哨兵”;3)分別隨機(jī)化處理與用戶輸入相關(guān)的數(shù)組、與輸入無(wú)關(guān)的數(shù)組、其他變量(包括函數(shù)指針)這3類數(shù)據(jù)結(jié)構(gòu)的內(nèi)存排列.這樣,通過(guò)在運(yùn)行時(shí)檢查Guard區(qū)域是否被覆寫,及時(shí)檢測(cè)出緩沖區(qū)溢出.同時(shí),這種結(jié)構(gòu)體內(nèi)部隨機(jī)化增加了猜測(cè)被攻擊對(duì)象內(nèi)存布局的難度.

      自動(dòng)結(jié)構(gòu)體隨機(jī)化[45]對(duì)占有相同大小內(nèi)存空間的域?qū)崿F(xiàn)內(nèi)存布局隨機(jī)化.這里的域包括CC++程序中出現(xiàn)的各種數(shù)據(jù)類型,最常用的是int,char,long等基本類型及結(jié)構(gòu)體.文獻(xiàn)[45]的自動(dòng)隨機(jī)化算法掃描包含數(shù)據(jù)變量的結(jié)構(gòu)體,構(gòu)建鄰接表,其縱向鏈節(jié)點(diǎn)保存不同類型(占內(nèi)存空間不同)的域,橫向鏈節(jié)點(diǎn)保存相同類型(占內(nèi)存空間相同)的域,遍歷每個(gè)橫向鏈表,對(duì)其域節(jié)點(diǎn)的串接順序進(jìn)行隨機(jī)化處理.

      這2種細(xì)粒度的隨機(jī)化方法部署在函數(shù)內(nèi)部、結(jié)構(gòu)體、類內(nèi)部,使攻擊者無(wú)法預(yù)知結(jié)構(gòu)體域排列的特點(diǎn),降低攻擊者越界篡改被攻擊對(duì)象的成功率.

      本節(jié)內(nèi)存布局隨機(jī)化方法的對(duì)比分析如表3所示:

      Table 3 Method Comparison about Memory Layout Randomization表3 內(nèi)存布局隨機(jī)化的方法比較

      3.2內(nèi)存越界讀寫保護(hù)

      攻擊者得到被攻擊對(duì)象的內(nèi)存布局后,會(huì)試圖獲取被攻擊對(duì)象的內(nèi)容.例如,棧內(nèi)存信息有其固定分布特征,攻擊者可以預(yù)知函數(shù)返回地址和可控變量的內(nèi)存排列,但卻無(wú)法直接打印出函數(shù)返回地址值,只能利用格式化字符串攻擊等獲得字符串后面的敏感信息.這里的越界讀寫不僅指內(nèi)存空間的越界,也包括邏輯上的越界訪問(wèn),如已釋放的空間里的信息不應(yīng)該被訪問(wèn),但越界獲取釋放對(duì)象的遺留信息造成UAF漏洞.內(nèi)存越界讀寫需要可控對(duì)象作為跳板,獲得被攻擊對(duì)象的訪問(wèn)權(quán)限.這里分別從界定可控對(duì)象訪問(wèn)范圍、設(shè)置被攻擊對(duì)象不可讀取權(quán)限2個(gè)方面分析內(nèi)存越界讀寫的防御方法.我們選取了虛表指針、數(shù)據(jù)指針、由指針(索引)訪問(wèn)的對(duì)象、棧內(nèi)的敏感信息4類典型的攻擊者可控對(duì)象,討論其合理的訪問(wèn)范圍,并分析當(dāng)針對(duì)4類可控對(duì)象的越界保護(hù)失效后,如何設(shè)置被攻擊對(duì)象(代碼指針、虛表指針等指向關(guān)鍵代碼的地址信息)的訪問(wèn)權(quán)限,才能使越界訪問(wèn)無(wú)效.

      3.2.1界定可控對(duì)象的合理訪問(wèn)范圍

      1) 虛表指針保護(hù)

      UAF漏洞和類型混淆漏洞會(huì)涉及到虛表指針,對(duì)虛表指針的保護(hù)可以抑制攻擊者進(jìn)行內(nèi)存越界讀寫,從而阻止內(nèi)存地址的泄漏.

      對(duì)于UAF漏洞,對(duì)象A被釋放后,其占用的地址空間被其他對(duì)象填充.因?yàn)镃++對(duì)象的前4B是虛表指針,攻擊者把占用對(duì)象的前4B填充為精心構(gòu)造的地址信息Addr(如與被攻擊對(duì)象關(guān)聯(lián)的固定指針變量vp的地址).攻擊者對(duì)懸掛指針解引用并調(diào)用對(duì)象A中的虛函數(shù)時(shí),程序轉(zhuǎn)向越界訪問(wèn)Addr處的內(nèi)容,造成關(guān)鍵地址信息泄漏.如果Addr處的變量是數(shù)據(jù)指針,則發(fā)生了指針類型沖突(把虛表指針視為代碼指針).為此,PointerScope[46]為X86指令系統(tǒng)設(shè)計(jì)了指令操作數(shù)類型限制規(guī)則,如MOV等數(shù)據(jù)傳輸指令的2個(gè)操作數(shù)的類型相同,MUL,DIV指令的操作數(shù)類型是整數(shù),JMP,JZ等控制流相關(guān)指令的操作數(shù)是控制指針,這種類型界定和類型傳播為類型推理算法提供了依據(jù),把指針誤用檢測(cè)轉(zhuǎn)化為類型沖突檢測(cè).

      對(duì)于類型混淆漏洞,攻擊者可通過(guò)解引用虛表指針,引起父類和子類虛函數(shù)的混淆調(diào)用,最終造成內(nèi)存越界訪問(wèn),如圖2中的vtableescape錯(cuò)誤.這類由虛表指針引起的內(nèi)存越界訪問(wèn),直接后果是錯(cuò)誤的虛函數(shù)調(diào)用.對(duì)虛函數(shù)調(diào)用的檢查,也能及時(shí)檢測(cè)虛表指針是否發(fā)生錯(cuò)誤解引用.SAFEDISPATCH[47]提供2種級(jí)別的C++虛函數(shù)調(diào)用檢查:針對(duì)對(duì)象實(shí)例的方法實(shí)現(xiàn)、針對(duì)對(duì)象的虛表.虛函數(shù)的作用是因?qū)ο罄^承而采用不同的策略實(shí)現(xiàn)函數(shù)名相同的不同方法.在編譯時(shí)分析調(diào)用虛函數(shù)的對(duì)象,確定其指針或引用的靜態(tài)類型,靜態(tài)類型必須聲明為該對(duì)象的基類指針或者引用.在運(yùn)行時(shí),C++的動(dòng)態(tài)調(diào)度機(jī)制確定調(diào)用虛函數(shù)的對(duì)象實(shí)際類型,是本身基類類型還是其子類類型.虛函數(shù)的調(diào)用保護(hù)包括靜態(tài)類層次分析(classhierarchyanalysis,CHA)和運(yùn)行時(shí)檢查2個(gè)階段.CHA分析需要編譯器對(duì)源代碼進(jìn)行靜態(tài)分析,確定虛函數(shù)合理的調(diào)用點(diǎn)范圍(基類和子類的虛函數(shù)),并以ValidM表格的形式表示.在運(yùn)行時(shí),把獲得的虛函數(shù)指針與ValidM中規(guī)定的方法實(shí)現(xiàn)對(duì)比,把虛函數(shù)的調(diào)用點(diǎn)控制在ValidM規(guī)定的合理范圍內(nèi).

      2) 數(shù)據(jù)指針保護(hù)

      指針是C或C++重要的數(shù)據(jù)結(jié)構(gòu),為程序的靈活性和可擴(kuò)展性提供了支持,攻擊者往往劫持函數(shù)返回地址、虛函數(shù)地址、或者其他指針,達(dá)到控制劫持或者數(shù)據(jù)劫持的目的.基本類型混淆漏洞以及修改指針?biāo)饕斐傻脑浇缭L問(wèn),都離不開(kāi)對(duì)指針的非法操作.

      SoftBound[48]通過(guò)對(duì)CC++語(yǔ)言中的數(shù)據(jù)指針進(jìn)行邊界檢查來(lái)保證內(nèi)存訪問(wèn)的安全性,可以保護(hù)內(nèi)存、寄存器、函數(shù)返回值中的指針.針對(duì)存儲(chǔ)在寄存器的指針值,生成對(duì)應(yīng)的基址base標(biāo)識(shí)和指針?lè)秶鷅ound標(biāo)識(shí).對(duì)于每一次指針的內(nèi)存訪問(wèn),SoftBound在其前面插入check函數(shù),來(lái)保證無(wú)指針越界訪問(wèn).針對(duì)存儲(chǔ)在內(nèi)存的指針,SoftBound會(huì)利用查找表,在指針地址與元數(shù)據(jù)表(包括指針對(duì)應(yīng)的base標(biāo)識(shí)和bound標(biāo)識(shí))之間建立映射,在取指針值時(shí),SoftBound會(huì)插入查表指令,來(lái)獲取該指針對(duì)應(yīng)的base和bound值;在存入指針值時(shí),SoftBound更新查找表里的相應(yīng)指針項(xiàng).

      類型化內(nèi)存模型[49]把C語(yǔ)言環(huán)境中的字節(jié)內(nèi)存模型抽象為由字節(jié)域和類型域組成的內(nèi)存塊,其中字節(jié)域即常規(guī)的有序數(shù)據(jù)內(nèi)容,類型域則是其對(duì)應(yīng)的類型集合.這種內(nèi)存安全模型的核心準(zhǔn)則是,保證按照數(shù)據(jù)類型的寫入類型mt的兼容類型mt′進(jìn)行讀取,而所占字節(jié)數(shù)量相等的2種數(shù)據(jù)類型則視為兼容類型.基于該安全準(zhǔn)則,在內(nèi)存讀寫操作中,該模型會(huì)先根據(jù)讀寫內(nèi)容的數(shù)據(jù)類型判斷目的內(nèi)存地址范圍是否合法.

      3) 對(duì)象邊界保護(hù)

      內(nèi)存操作函數(shù)的惡意利用破壞了原有的對(duì)象邊界,整數(shù)溢出漏洞惡意修改了訪問(wèn)對(duì)象的索引,本節(jié)討論這些攻擊的檢測(cè)與防御.

      SoftBound從指針保護(hù)的角度阻止了內(nèi)存的越界訪問(wèn).同理,保護(hù)用指針訪問(wèn)的對(duì)象也可以阻止內(nèi)存的越界訪問(wèn).WIT(writeintegritytesting)[50]對(duì)中間語(yǔ)言代碼進(jìn)行靜態(tài)的指針?lè)治龊蛯懓踩苑治?指針?lè)治鼍褪菍ふ颐總€(gè)指針的指向?qū)ο蟮募?包括局部變量、全局變量及動(dòng)態(tài)分配的內(nèi)存對(duì)象),即PTS(points-toset).每個(gè)指針及其對(duì)應(yīng)的PTS安全級(jí)別相同(以顏色標(biāo)記安全級(jí)別).寫安全性分析就是確定每條指令的安全級(jí)別.寫指令與其目標(biāo)內(nèi)存地址顏色一致,間接調(diào)用指令與其對(duì)應(yīng)的目標(biāo)函數(shù)顏色一致.但是,WIT并不能阻止越界讀操作,因?yàn)樽x指令被默認(rèn)為安全級(jí)別.而越界讀操作會(huì)引發(fā)內(nèi)存關(guān)鍵信息的泄漏,如內(nèi)存地址泄漏.

      WIT把對(duì)象邊界與其對(duì)應(yīng)的語(yǔ)義(同一指針指向的PTS,寫指令的目標(biāo)內(nèi)存地址,間接調(diào)用指令的目標(biāo)函數(shù))聯(lián)系起來(lái).BaggyBoundsChecking[51]根據(jù)對(duì)象類型不同,在程序執(zhí)行的不同階段記錄對(duì)象邊界信息.在每次為對(duì)象分配內(nèi)存時(shí),BaggyBoundsChecking會(huì)多分配若干字節(jié),使分配內(nèi)存大小滿足2n.它利用內(nèi)存對(duì)象邊界表[52]記錄對(duì)象邊界信息,根據(jù)malloc(·),free(·)等函數(shù)更新堆塊的邊界信息,在調(diào)用函數(shù)和函數(shù)返回時(shí)更新棧內(nèi)局部變量的邊界信息,在程序啟動(dòng)時(shí)更新全局變量的邊界信息.

      對(duì)內(nèi)存操作函數(shù)的惡意利用會(huì)破壞原有的對(duì)象邊界.基于規(guī)則的代碼補(bǔ)丁[53]對(duì)CC++中可能造成緩沖區(qū)溢出的代碼段進(jìn)行修改并重新編譯,在不改變程序邏輯基礎(chǔ)上,很大程度上阻止內(nèi)存函數(shù)越界復(fù)制等漏洞.其中補(bǔ)丁規(guī)則比如用函數(shù)strncpy替代函數(shù)strcpy,對(duì)索引值進(jìn)行取模運(yùn)算限制訪問(wèn)范圍,對(duì)指針運(yùn)算結(jié)果添加必要檢查,對(duì)內(nèi)存輸入函數(shù)添加長(zhǎng)度參數(shù)等等.在目標(biāo)緩沖區(qū)的末尾添加“

      灌南县| 大田县| 文登市| 永新县| 环江| 百色市| 布拖县| 新邵县| 娄烦县| 安平县| 台州市| 布尔津县| 英吉沙县| 伊宁县| 五大连池市| 兰溪市| 台山市| 南陵县| 呈贡县| 宿州市| 九龙县| 宝清县| 灵丘县| 永泰县| 紫阳县| 汤阴县| 荣昌县| 武定县| 会理县| 麦盖提县| 汝州市| 鄯善县| 庄河市| 马公市| 陆川县| 康乐县| 怀化市| 临城县| 阳新县| 大洼县| 许昌市|