呂洪艷,李 薈
(東北石油大學(xué)計算機(jī)與信息技術(shù)學(xué)院,黑龍江大慶163318)
PaX是Linux系統(tǒng)核心的安全補(bǔ)丁包,它給系統(tǒng)帶來了安全方面的新希望。PaX是Hardened Gentoo Linux系統(tǒng)的組成部分,它的部分特性也被OpenBSD操作系統(tǒng)采用。
由于操作系統(tǒng)并不知道一個應(yīng)用程序的具體功能是什么,所以操作系統(tǒng)僅能從控制程序的執(zhí)行環(huán)境出發(fā)來增強(qiáng)安全性。為了阻止有人利用現(xiàn)有操作系統(tǒng)和應(yīng)用程序的弱點獲取非正常的訪問權(quán)利,操作系統(tǒng)必須阻止程序在執(zhí)行的時候有以下情況發(fā)生:①引入和執(zhí)行沒有安全保證的代碼;② 不按正常的順序執(zhí)行現(xiàn)有的代碼;③按正常的順序執(zhí)行現(xiàn)有的代碼但參數(shù)被修改。
PaX應(yīng)用了兩種方法來幫助Linux系統(tǒng)抵御大多數(shù)的緩沖區(qū)溢出攻擊。一是為Linux提供了“緩沖區(qū)不可執(zhí)行”特性,這會阻止攻擊者執(zhí)行插入到緩沖區(qū)中的攻擊代碼;二是“地址空間的隨機(jī)布局”,如果一個應(yīng)用程序滿足PIE(Position Independent Executable)格式,則PaX會在各個段裝入內(nèi)存時,采用不規(guī)則的布局方案,以增加攻擊者入侵的難度。
設(shè)置攻擊代碼所在的內(nèi)存空間為“不可執(zhí)行”,這樣即使程序中的緩沖區(qū)被溢出也不能執(zhí)行攻擊代碼,這種技術(shù)被稱為不可執(zhí)行緩沖區(qū)技術(shù)[3]。
在早期的Unix系統(tǒng)中,只允許程序在代碼段中執(zhí)行[4],但近來的Unix和Windows系統(tǒng)由于要實現(xiàn)更好的性能和功能,往往在數(shù)據(jù)段中動態(tài)地放入可執(zhí)行代碼,這也是緩沖區(qū)溢出問題的根源。由于絕大多數(shù)程序不會在棧段里放置可執(zhí)行代碼,所以通過禁止執(zhí)行棧段內(nèi)的代碼可以提高系統(tǒng)的安全性。“不可執(zhí)行的棧”就是如果檢查發(fā)現(xiàn)返回地址在棧中,則禁止執(zhí)行這些代碼,報告錯誤并記錄。設(shè)置“不可執(zhí)行的?!?,僅能對付“把攻擊代碼植入棧中”這種最普通的攻擊方式,但攻擊者還有其他的方法,例如把攻擊代碼植入“堆空間”和“靜態(tài)數(shù)據(jù)段”中。利用PaX則可以實現(xiàn)更為全面的保護(hù)。
PaX的“緩沖區(qū)不可執(zhí)行”機(jī)制有三個特性:第一個特性是為內(nèi)存頁增加的“不可執(zhí)行”屬性(由于IA-32體系結(jié)構(gòu)具有“分段管理”和“分頁管理”兩種方式,所以這部分由PAGEEXEC和SEGMEXEC兩個模塊組成);在操作系統(tǒng)核心可以實現(xiàn)“不可執(zhí)行”的頁之后,就可以獲得第二個特性——將棧段、堆空間、內(nèi)存的“匿名映射”所在的內(nèi)存區(qū)標(biāo)記為“不可執(zhí)行”,并且在 ELF(Executable and Linkable Format,可執(zhí)行可鏈接格式)文件映射到內(nèi)存時將所有沒有“可執(zhí)行”標(biāo)記的數(shù)據(jù)區(qū)都缺省標(biāo)記為“不可執(zhí)行”;第三個特性就是修改mmap()和 mpretect()功能(由MPROTECT模塊實現(xiàn)),防止它們在執(zhí)行時會破壞數(shù)據(jù)區(qū)的“不可執(zhí)行”狀態(tài)。PaX的這三個特性實質(zhì)上是增強(qiáng)了系統(tǒng)內(nèi)存訪問控制,來阻止沒有安全保證的代碼被執(zhí)行。下面詳細(xì)介紹一下各個模塊的實現(xiàn)原理。
由上述分析可知,在X = 20D處管道內(nèi)的二次流已經(jīng)基本消失,顆粒的體積分?jǐn)?shù)分布基本恢復(fù)到直管段充分發(fā)展態(tài),對比圖6b)、圖6c)和圖7b)、圖7c) X = 5D和X = 20D處各曲線可看出,在X = 5D處的體積分?jǐn)?shù)曲線較X = 20D處仍有較明顯的變形。由于在X = 5D處泥漿不再受到離心力的作用,顆粒分布的改變主要由殘留的二次流渦流作用引起,故從顆粒體積分?jǐn)?shù)分布的梯度可反映出殘留二次流的強(qiáng)度。
PAGEEXEC:此模塊為“分頁管理”下的IA-32系列處理器實現(xiàn)了具有“不可執(zhí)行”的頁。從80386開始的IA-32系列處理器都支持存儲器分頁管理機(jī)制。段管理機(jī)制實現(xiàn)虛擬地址到線性地址的轉(zhuǎn)換,分頁管理機(jī)制實現(xiàn)線性地址到物理地址的轉(zhuǎn)換。如果不啟用分頁管理機(jī)制,那么線性地址就是物理地址。
IA-32中頁目錄表和頁表中的表項都采用如表1所示的格式。
表1 IA-32中頁目錄表和頁表中的表項Tab.1 List items of contents page table and page table in IA-32
IA-32不僅提供段級保護(hù),也提供頁級保護(hù)。在表1所示頁目錄表和頁表的表項中保護(hù)屬性位R/W和U/S就是用于對頁進(jìn)行保護(hù)。其含義如表2所示。
從安全性的角度來說,如果程序地址空間中的某些數(shù)據(jù)不需要被執(zhí)行,那么它們就不應(yīng)該具有被執(zhí)行的能力,就應(yīng)該把這些數(shù)據(jù)標(biāo)記為“不可執(zhí)行”。更進(jìn)一步,如果一個程序不會在運行的時候動態(tài)產(chǎn)生程序代碼,那么它也不應(yīng)該具有這樣的能力,所以,核心應(yīng)該有能力阻止內(nèi)存頁的狀態(tài)在“可寫”和“可執(zhí)行”之間轉(zhuǎn)換或同時擁有“可寫”和“可執(zhí)行”屬性。由于IA-32硬件結(jié)構(gòu)的限制,不能直接實現(xiàn)“不可執(zhí)行”屬性,所以PaX利用PAGEEXEC模塊為“分頁管理”下的IA-32系列處理器實現(xiàn)了這一功能。
表2 IA-32中頁目錄表和頁表中的表項中R/W和U/S的含義Tab.2 Meaning of R/W and U/S in the list items of contents page table and page table in IA-32
從Pentium系列開始,Intel的CPU都將原來的一個TLB(Translation Lookaside Buffer)分割成了兩個,也就是說為代碼和數(shù)據(jù)的虛實地址轉(zhuǎn)換各建立了一個Cache[分別稱為ITLB(Instruction-TLB,指令頁表緩存)/DTLB(Data-TLB,數(shù)據(jù)頁表緩存)]。使用了TLB,可以大大加快存儲器的訪問速度。作為一種用途特殊的Cache,TLB容量是有限的,當(dāng)TLB裝滿數(shù)據(jù)的時候,CPU就會淘汰舊的數(shù)據(jù)讓出空間裝新的數(shù)據(jù)。在IA-32中這個過程由硬件自動實現(xiàn),如果硬件在執(zhí)行時發(fā)生錯誤,就會觸發(fā)“頁錯誤”異常,轉(zhuǎn)由軟件來解決,這里的軟件(也就是異常處理程序)就是實現(xiàn)內(nèi)存頁“不可執(zhí)行”屬性的關(guān)鍵。如果有內(nèi)存頁需要設(shè)置為“不可執(zhí)行”,則將此頁頁表中的U/S位設(shè)置為“0”,就是設(shè)置為需要“系統(tǒng)特權(quán)”才能訪問。這樣在用戶態(tài)下進(jìn)行這樣的頁面訪問就會引發(fā)異常,在此異常處理程序中,會判斷這是要“執(zhí)行指令”還是正常的數(shù)據(jù)讀寫(通過比較當(dāng)前指令的地址和產(chǎn)生錯誤的目標(biāo)地址就可以做出判斷)。如果是要“執(zhí)行指令”,這就檢測到了試圖執(zhí)行“不可執(zhí)行”的數(shù)據(jù);如果是正常的數(shù)據(jù)讀寫,就將頁表中相應(yīng)表項裝入DTLB中并將U/S位設(shè)置為“1”,以便進(jìn)行用戶級訪問。注意:由于只有DTLB中的U/S位設(shè)置為“1”而頁表中的U/S位仍是“0”,所以在下次訪問同一頁時還會觸發(fā)異常,所以不會給攻擊者留下可乘之機(jī)。簡而言之,PAGEEXEC是在不影響數(shù)據(jù)訪問的情況下,“重載”了U/S位來標(biāo)記內(nèi)存頁的“可執(zhí)行/不可執(zhí)行”屬性。
SEGMEXEC:IA-32系列也可以不啟用分頁管理機(jī)制,這時利用此模塊實現(xiàn)“不可執(zhí)行”屬性。SEGMEXEC的工作道理很簡單:把3GB的用戶內(nèi)存空間分為兩份,限制數(shù)據(jù)段描述符訪問0~1.5 GB 這個區(qū)間,代碼段描述符訪問 1.5~3 GB這個區(qū)間。這樣的劃分,就可以將訪問普通數(shù)據(jù)(不可執(zhí)行)和讀取指令(可執(zhí)行)區(qū)分開,在0~1.5 GB范圍內(nèi)讀取指令就會引發(fā)異常。
MPROTECT:此模塊用來對 mmap()和mpretect()原有功能加上必要的訪問控制,以便阻止在特定的地址空間中引入新的“可執(zhí)行”數(shù)據(jù)。新的訪問控制功能用來完成如下功能:
(1)阻止創(chuàng)建“可執(zhí)行”的匿名映射;
(2)阻止創(chuàng)建“可執(zhí)行”并且“可寫”的文件映射;
(3)阻止將“可執(zhí)行”但“只讀”的文件映射轉(zhuǎn)變?yōu)椤翱蓪憽钡奈募成?,除非是對ET_DYN格式的ELF文件進(jìn)行重定位;
(4)阻止將“不可執(zhí)行”的文件映射轉(zhuǎn)變?yōu)椤翱蓤?zhí)行”的文件映射。
在Linux的核心有一個vm_flags域用來存放每個映射的訪問屬性。PaX設(shè)置了四個預(yù)定義值來說明每個映射區(qū)的狀態(tài):VM_WRITE,VM_EXEC,VM_MAYWRITE,VM_MAYEXEC。如果某個內(nèi)存區(qū)具有VM_WRITE屬性,那么它也一定具有VM_MAYWRITE屬性;VM_EXEC和VM_MAYEXEC的關(guān)系也類似。
在正常的Linux的核心中,某個映射區(qū)可以同時擁有“可執(zhí)行”和“可寫”屬性,而PaX就是要阻止這種情況出現(xiàn),以便防止用戶可以隨意在“可執(zhí)行”的內(nèi)存區(qū)引入新的可執(zhí)行代碼。所以,映射區(qū)的所有合法狀態(tài)只有四個:VM_MAYWRITE,VM_MAYEXEC,VM_WRITE|VM_MAYWRITE,VM_EXEC|VM_MAYEXEC。由于這樣的設(shè)計,攻擊者就只有一種方法可以在“可執(zhí)行”的內(nèi)存區(qū)引入新的可執(zhí)行代碼,那就是使用帶有PROT_EXEC參數(shù)的mmap()來引入一個文件。這樣一來,進(jìn)攻的意圖就過于明顯了,很容易被其他方法阻止。
對于大部分合法程序而言,不會在內(nèi)存的“不可執(zhí)行”區(qū)放置代碼,但在Linux中也有兩個“常見”的例外,這時的可執(zhí)行代碼必須放置在棧段中:①信號傳遞:Linux通過向進(jìn)程棧填寫代碼然后引發(fā)中斷來執(zhí)行棧中的代碼以便實現(xiàn)向進(jìn)程發(fā)送 Unix信號。② GCC(GNU Compiler Collection,GNU編譯器套件)的函數(shù)嵌套:GCC在棧段中放置了可執(zhí)行代碼以便支持函數(shù)的嵌套定義和引用。為了支持這兩種情況,PaX使用EMUTRAMP模塊來模擬這兩個程序段的執(zhí)行。無論何時,如果試圖執(zhí)行“不可執(zhí)行”區(qū)中代碼,PAGEEXEC或SEGMEXEC模塊都會觸發(fā)一個“頁出錯”異常,所以EMUTRAMP模塊就放置在這個異常處理程序中,來把“不可執(zhí)行”區(qū)中代碼取出來執(zhí)行。
隨著開放源代碼的出現(xiàn)和普及,雖然共享軟件的穩(wěn)定性在不斷增加,但軟件中的弱點也更容易尋找,例如可以很容易地從源代碼中計算出棧的幀地址。很多著名的共享軟件像bind,wu_ftp,apache和 sendmail,等等,都被找出過漏洞并被攻擊。
ASLR機(jī)制的原理是通過在虛擬地址空間中的各個段的位置上引入隨機(jī)性,來阻止攻擊者利用那些必須預(yù)先知道內(nèi)存地址的系統(tǒng)弱點。一般情況下,Linux系統(tǒng)的虛擬地址空間的布置方案如圖1所示。
圖1 Linux系統(tǒng)地址空間布置方案Fig.1 Layout scheme of system address space in Linux
一些攻擊方法利用了某些程序在段中存在固定地址(例如當(dāng)前棧指針或者動態(tài)庫的地址)的弱點,修改這些地址指向已經(jīng)注入的攻擊代碼來發(fā)動攻擊。ASLR可以隨機(jī)設(shè)置棧段、堆空間、動態(tài)庫和可執(zhí)行段的位置,令上述進(jìn)攻方法失去作用。雖然攻擊者可以對地址進(jìn)行一些猜測,但猜對的可能性很低,而且猜錯后攻擊程序?qū)⒃噲D訪問“不可執(zhí)行”區(qū),就會被NOEXEC發(fā)現(xiàn)。由于程序每次執(zhí)行時都會設(shè)置新的隨機(jī)位置,所以上次猜測錯誤不會對下次猜測有任何幫助。
ASLR由四個部分組成:RANDUSTACK,RANDKSTACK,RANDMMAP,RANDEXEC。
RANDUSTACK:此模塊負(fù)責(zé)產(chǎn)生用戶棧的隨機(jī)地址。程序在執(zhí)行execve()系統(tǒng)調(diào)用的時候,Linux核心會建立程序的用戶棧,這個過程分為兩步:首先核心分配適量的物理內(nèi)存頁,然后把這些內(nèi)存頁映射到程序的虛擬內(nèi)存空間中。在IA-32系列中,Linux核心會把棧段映射到地址空間的最高端(地址為0xbfffffff),并向下增長(圖1)。在這兩步實現(xiàn)的過程中,RANDUSTACK都會引入隨機(jī)值來修正:物理內(nèi)存地址的隨機(jī)修正量為4KB(過大的物理內(nèi)存地址的隨機(jī)修正量可能會形成內(nèi)存碎片),虛擬內(nèi)存地址的修正量達(dá)256MB。
RANDKSTACK:此模塊負(fù)責(zé)為程序核心棧引入隨機(jī)性。每個程序都會擁有大小為兩個內(nèi)存頁的核心棧,在發(fā)生系統(tǒng)調(diào)用、硬件中斷和CPU異常的時候,系統(tǒng)會從用戶態(tài)切換到核心態(tài),這些內(nèi)存頁供核心在此時使用。在這些處理結(jié)束的時候,系統(tǒng)會從核心態(tài)切換回用戶態(tài),正常情況下,這時的核心棧是空的。這就使得在每次使用核心棧之前可以為它分配一個新的地址,而不是像用戶棧那樣在整個程序執(zhí)行期間地址保持不變。因為系統(tǒng)調(diào)用是潛在的攻擊目標(biāo),每次進(jìn)行系統(tǒng)調(diào)用時,核心棧的地址都是不同的就成為一個重要的優(yōu)點。RANDKSTACK為核心棧引入的隨機(jī)修正量為128個字節(jié)[5]。
RANDMMAP:此模塊為所有的文件映射和匿名映射建立隨機(jī)性,包括系統(tǒng)調(diào)用brk()和mmap()、堆空間的管理、裝入可執(zhí)行文件或者庫。這些內(nèi)存映射由核心的do_mmap()接口來完成,所以RANDMMAP模塊就“掛鉤”在這個接口上。Linux核心在分配堆空間的時候,總是從未使用的物理空間的最低端開始尋找第一個足夠大而又未使用的區(qū)域分配出去(即首次擬和算法)。RANDMMAP在這個過程中增加了兩個隨機(jī)量:搜尋物理空間的起點不再是從最低端開始,而是加上了4K的隨機(jī)修正量;而虛擬內(nèi)存地址也具有的256MB的修正量。在把文件映射到內(nèi)存的時候僅為虛擬內(nèi)存地址提供了256MB的修正量。只有ET_DYN格式的ELF文件的映射是由RANDMMAP管理的,而EF_EXEC格式的ELF文件由RANDEXEC來管理。
RANDEXEC:在編譯器鏈接EF_EXEC格式的ELF文件的時候,假設(shè)這種文件只會在固定的地址上執(zhí)行,所以不需要過多的重定位信息,這就導(dǎo)致為這種文件的內(nèi)存映射建立隨機(jī)性是比較困難的。解決的辦法是為EF_EXEC文件在內(nèi)存中建立兩個完全相同的映射區(qū),第一個在它的原始地址上,另一個在一個隨機(jī)地址上,而第一個映射區(qū)被標(biāo)記為“不可執(zhí)行”。如果試圖執(zhí)行第一個映射區(qū)中的代碼,就會產(chǎn)生“頁出錯”異常,在異常處理程序中會把頁面“重定向”到“隨機(jī)區(qū)”去。自動的“重定向”功能會使隨機(jī)性的引入失去意義,所以要在“重定向”之前進(jìn)行各種檢查;例如如果有人利用“重定向”功能發(fā)動攻擊,就會在用戶棧中留有相應(yīng)的信息,這時RANDEXEC 就會終止“重定向”功能[6]。
按攻擊的目標(biāo)分類,緩沖區(qū)溢出攻擊方法共有 20 種[7-8],PaX 對各種攻擊方法都有很好的保護(hù)。NOEXEC模塊會阻止程序執(zhí)行不安全的代碼;ASLR模塊可以阻止那些必須利用預(yù)先知道內(nèi)存地址的弱點才能發(fā)動的攻擊。有很多人研究過怎樣突破PaX的防護(hù),但很少有成功的。
在上面列出的三種必須阻止的程序異常行為中,NOEXEC模塊會阻止情況①(見本文2節(jié))的出現(xiàn),ASLR模塊僅能以一定的概率阻止情況②和情況③的出現(xiàn)。完全阻止后兩種情況的出現(xiàn)是要付出很大的性能代價,所以PaX的未來研究目標(biāo)就是怎樣在安全性和性能之間做出合理的折中。
本文詳細(xì)描述和分析了Linux系統(tǒng)緩沖區(qū)溢出的核心防衛(wèi)方法。由于該攻擊方式目前很常見,難以在短期之內(nèi)徹底解決,并在未來的多年一直困擾著計算機(jī)安全,因而目前該問題的研究工作仍具有實際意義。
[1] John Wilander,Mariam Kamkar.A comparsion of publicly available tools for dynamic buffer overflow prevention[C]∥Network and Distributed System Security Symposium Conference Proceedings.California,USA:[s.n.],2003:23-24.
[2] Crispin Cowan,Perry Wagle Buffer.Overflows:attacks and defense for the vulnerability of the decade[C]∥DARPA Information Survivability Conference and Exposition.Hilton Head,USA:[s.n.],2000:119-129.
[3] 賴雋文,楊壽保.Linux系統(tǒng)中防止緩沖區(qū)溢出型攻擊的新技術(shù)探討[J].計算機(jī)應(yīng)用研究,1999,11(11):11-13.LAI Junwen,YANG Shoubao,The new technology discussion of preventing buffer overflow attacks in Linux system[J].Application Research of Computers,1999,11(11):11-13.
[4] 孫文豪.緩沖區(qū)溢出的安全隱患[J].網(wǎng)絡(luò)安全技術(shù)與應(yīng)用,2010(5):9-10.SUN Wenhao.The safe hidden trouble of buffer overflow[J].Network Security Technology & Application,2010(5):9-10.
[5] 寧蒙.網(wǎng)絡(luò)信息安全與防范技術(shù)[M].南京:東南大學(xué)出版社,2006.NING Meng.The network information security and prevention technology[M].Nanjing:Southeast University Press,2006.
[6] 卿斯?jié)h,蔣建春.網(wǎng)絡(luò)攻防技術(shù)原理與實踐[M].北京:科學(xué)出版社,2004.QING Sihan,JIANG Jianchun.Network attack and defense technology principle and practice[M].Beijing:Science Press,2004.
[7] 陳莉君.Linux操作系統(tǒng)原理與應(yīng)用[M].北京:清華大學(xué)出版社,2006.CHEN Lijun.Principle and application of Linux operating system[M].Beijing:Tsinghua University Press,2006.
[8] 楊明軍.實戰(zhàn)Linux編程精髓[M].北京:中國電力出版社,2005.YANG Mingjun.Actual programming essence of Linux[M].Beijing:China Electric Power Press,2005.