林鍵 郭玉東 周少皇
摘要:在可執(zhí)行和可鏈接格式(ELF)的可執(zhí)行程序中,存在一個(gè)全局偏移表(GOT),用于存放引用庫(kù)函數(shù)的絕對(duì)地址,但是在Linux系統(tǒng)中,GOT解引用和GOT覆寫(xiě)是兩種比較常用的漏洞利用方法。通過(guò)分析GOT的特性,提出并實(shí)現(xiàn)了基于地址隨機(jī)和段隔離的GOT保護(hù)方法。通過(guò)修改Linux的可執(zhí)行程序加載器,將與GOT有數(shù)據(jù)指向關(guān)系的節(jié)均加載到隨機(jī)內(nèi)存地址;同時(shí)使用段隔離技術(shù),對(duì)GOT的代碼引用的指令使用一個(gè)新的段寄存器進(jìn)行間接引用。實(shí)驗(yàn)結(jié)果證明,該方法不僅能夠有效地防御針對(duì)GOT的漏洞利用方法,而且性能損耗極低,只有平均2.9ms的額外開(kāi)銷(xiāo)。
關(guān)鍵詞:
全局偏移表保護(hù);地址隨機(jī);段隔離;全局偏移表解引用;全局偏移表覆寫(xiě)
中圖分類(lèi)號(hào): TP309.2 文獻(xiàn)標(biāo)志碼:A
0引言
Linux是一套免費(fèi)使用和自由傳播的操作系統(tǒng),廣泛應(yīng)用于文件服務(wù)器、數(shù)據(jù)庫(kù)服務(wù)器、Web服務(wù)器、應(yīng)用程序服務(wù)器等服務(wù)器之中。服務(wù)器作為提供基本服務(wù)的設(shè)備,需要保證其提供服務(wù)的可靠性和安全性。形形色色的針對(duì)服務(wù)器上的攻擊,已經(jīng)導(dǎo)致諸多嚴(yán)重的后果:敏感數(shù)據(jù)丟失或損失、系統(tǒng)受損以及經(jīng)濟(jì)損失等。其中,通過(guò)挖掘軟件漏洞,利用漏洞進(jìn)行攻擊是最為常見(jiàn)的攻擊方法。這些漏洞的成因主要是在軟件設(shè)計(jì)和實(shí)現(xiàn)方面對(duì)如何保護(hù)系統(tǒng)考慮不周,在開(kāi)發(fā)實(shí)踐方面對(duì)消除會(huì)導(dǎo)致漏洞的實(shí)現(xiàn)瑕疵關(guān)注不夠。攻擊者在發(fā)現(xiàn)軟件產(chǎn)品中的漏洞后,可以迅速開(kāi)發(fā)出漏洞利用的腳本,繼而使用這些腳本威脅計(jì)算機(jī)的安全。為了增加漏洞利用的難度,防御者在系統(tǒng)中部署了漏洞利用緩解技術(shù),如地址空間布局隨機(jī)化(Address Space Layout Randomization, ASLR)[1]和數(shù)據(jù)執(zhí)行保護(hù)(Data Execution Prevention, DEP)[2]等,但是即使在部署了以上緩解技術(shù)的系統(tǒng)中,通過(guò)利用全局偏移表(Global Offset Table, GOT),可以繞過(guò)這些緩解技術(shù)從而實(shí)現(xiàn)漏洞的完美利用。
全局偏移表,是Linux下可執(zhí)行程序中一個(gè)專(zhuān)門(mén)的節(jié),用于存放依賴(lài)庫(kù)函數(shù)的目的地址。因?yàn)檠舆t解析機(jī)制,全局偏移表中的庫(kù)函數(shù)只有在第一次真正引用時(shí)才解析,并在解析后將目的地址寫(xiě)入全局偏移表,為此,全局偏移表具有可寫(xiě)權(quán)限。目前Linux雖然采用地址空間布局隨機(jī)化技術(shù),對(duì)棧、堆、共享庫(kù)進(jìn)行了隨機(jī)化,但是可執(zhí)行程序仍然加載到固定內(nèi)存地址,因此全局偏移表仍然加載到固定內(nèi)存地址,因此,全局偏移表是固定內(nèi)存的可寫(xiě)函數(shù)指針集合。正是由于全局偏移表的這種特性,存在兩種常見(jiàn)的使用全局偏移表的漏洞利用方法:全局偏移表解引用技術(shù)[3-4]和全局偏移表覆寫(xiě)技術(shù)[5-6]。全局偏移表解引用技術(shù),通過(guò)信息泄露漏洞,讀取全局偏移表中已解析的庫(kù)函數(shù)地址,可以得到該函數(shù)的真實(shí)地址,為此可以計(jì)算得到相應(yīng)動(dòng)態(tài)鏈接庫(kù)的基地址,從而繞過(guò)地址空間布局隨機(jī)化的防護(hù);全局偏移表覆寫(xiě)技術(shù),通過(guò)任意地址寫(xiě)漏洞,修改全局偏移表中庫(kù)函數(shù)的地址,能夠劫持程序控制流。
針對(duì)這些攻擊方式,有研究者提出了一些相應(yīng)的保護(hù)方法。完全地只讀重定位(Full Relocation ReadOnly, Full RELRO)[7-8],禁用延遲解析,在鏈接器初始化階段將所有全局偏移表中函數(shù)的值解析為真正函數(shù)的地址,然后將全局偏移表所在內(nèi)存頁(yè)標(biāo)記為只讀權(quán)限,很好地防止了對(duì)全局偏移表的改寫(xiě)。安全全局偏移表(Secure Global Offset Table, SecGOT)[9-10],通過(guò)重寫(xiě)可執(zhí)行和可鏈接格式(Executable and Linkable Format, ELF)[11]文件,并用定制的鏈接器進(jìn)行鏈接,在鏈接時(shí)將全局偏移表移動(dòng)到隨機(jī)的內(nèi)存中;同時(shí)修改訪問(wèn)全局偏移表的指令。
Full RELRO方法中,全局偏移表仍然位于固定內(nèi)存地址,因此可以對(duì)全局偏移表內(nèi)容進(jìn)行直接讀取,不能防止全局偏移表解引用。在啟動(dòng)時(shí)需對(duì)可執(zhí)行程序使用的所有庫(kù)函數(shù)進(jìn)行解析,而函數(shù)符號(hào)解析過(guò)程相對(duì)比較耗時(shí),對(duì)程序啟動(dòng)過(guò)程的性能影響較大。SecGOT方法隨機(jī)不夠徹底,雖然攻擊者不能立刻知道全局偏移表地址,但是指向全局偏移表的數(shù)據(jù)和代碼引用全局偏移表的指令仍位于固定地址,通過(guò)讀取這些固定地址,可以計(jì)算得到全局偏移表的地址。針對(duì)這兩種方法的不足,本文提出一種新的保護(hù)方法:基于地址隨機(jī)和段隔離的全局偏移表保護(hù)(Global Offset Table protection based Randomization, GOTRand)方法。在可執(zhí)行程序加載時(shí),不僅將全局偏移表加載到隨機(jī)的內(nèi)存中,而且將所有對(duì)全局偏移表有數(shù)據(jù)指向關(guān)系的節(jié)也加載到隨機(jī)內(nèi)存中。同時(shí),引用一個(gè)新的段寄存器,利用段的隔離特性,將所有對(duì)全局偏移表進(jìn)行代碼引用的指令修改為使用該新段寄存器進(jìn)行間接引用。
1ELF結(jié)構(gòu)
ELF又稱(chēng)可執(zhí)行和可鏈接格式,是Linux系統(tǒng)的主要可執(zhí)行文件格式。ELF有詳細(xì)的格式規(guī)范[8],此處僅介紹ELF中與GOT有關(guān)聯(lián)的結(jié)構(gòu)。在ELF中,存在一個(gè)動(dòng)態(tài)節(jié),用于提供動(dòng)態(tài)鏈接所需的信息,其中包含了GOT節(jié)所在地址。GOT節(jié),用于存在全局函數(shù)的目的地址,也就是本文所要重點(diǎn)保護(hù)的GOT。
為了實(shí)現(xiàn)對(duì)GOT中外部函數(shù)的調(diào)用,在ELF中還定義了一個(gè)過(guò)程鏈接表(Procedure Linkage Table, PLT)。GOT中的每一個(gè)函數(shù)在PLT中都有一個(gè)對(duì)應(yīng)的項(xiàng),記GOT第n個(gè)函數(shù)在PLT中的對(duì)應(yīng)項(xiàng)為PLTn,如第1個(gè)函數(shù)在PLT中的對(duì)應(yīng)項(xiàng)為PLT1。特殊地,在PLT節(jié)的最開(kāi)始,定義了一個(gè)特殊的表項(xiàng),記為PLT0,不對(duì)應(yīng)任何函數(shù)。PLT對(duì)應(yīng)的結(jié)構(gòu)如圖1所示。除了PLT0之外,其余各項(xiàng)都是由三條指令構(gòu)成的程序片段。PLT項(xiàng)中第一條跳轉(zhuǎn)指令(jmp)完成對(duì)GOT的代碼引用。
ELF中,對(duì)符號(hào)的動(dòng)態(tài)解析采用了一種延遲加載的方式[9]。如圖2所示,動(dòng)態(tài)鏈接器初始化后,GOT節(jié)中除了前3項(xiàng)用于特殊用途外,其余的各項(xiàng)均指向到相應(yīng)的PLT項(xiàng)的第2條指令。當(dāng)首次調(diào)用某函數(shù)時(shí),程序才通過(guò)符號(hào)解析函數(shù)_dl_runtime_resolve()解析獲取函數(shù)的真正地址,并填入到GOT對(duì)應(yīng)項(xiàng)中。
2GOTRand的設(shè)計(jì)
針對(duì)GOT的漏洞利用技術(shù)中,GOT解引用技術(shù)可通過(guò)一次任意地址信息泄露將位于固定地址的GOT中的內(nèi)容泄露出來(lái),即得到函數(shù)的真正地址,根據(jù)這個(gè)函數(shù)在庫(kù)中的相對(duì)偏移,可以得到整個(gè)動(dòng)態(tài)庫(kù)加載的基地址。GOT覆寫(xiě)技術(shù),則是通過(guò)一次任意地址寫(xiě)漏洞,將位于固定地址的GOT中的內(nèi)容改寫(xiě)為惡意代碼的入口點(diǎn),從而劫持程序的控制流程。
通過(guò)分析兩種漏洞利用技術(shù),可以發(fā)現(xiàn)它們主要利用了GOT的兩個(gè)特點(diǎn):1)GOT中存放的都是函數(shù)指針,且具有可寫(xiě)權(quán)限,通過(guò)修改GOT即可獲取到程序執(zhí)行流程;2)GOT加載到內(nèi)存中的地址是固定的,通過(guò)對(duì)ELF程序的解析,可以獲取其GOT加載的內(nèi)存地址。第1個(gè)特點(diǎn)是由GOT和延遲解析的特性所決定的,對(duì)其改進(jìn)將帶來(lái)較大性能損耗。故主要考慮從第2個(gè)特點(diǎn)進(jìn)行改進(jìn),對(duì)GOT地址進(jìn)行隨機(jī)化,使其地址不再固定。隨機(jī)化處理需要保證以下兩點(diǎn):1)GOT地址改變之后程序依舊能正常運(yùn)行;2)GOT隨機(jī)之后能夠有效防御針對(duì)GOT的攻擊方法:GOT解引用和GOT覆寫(xiě),保證在隨機(jī)后GOT的地址不能被攻擊者間接獲取得到。
2.1程序的正常運(yùn)行
在ELF中,不同的節(jié)之間有一定的指向關(guān)系,通過(guò)某個(gè)節(jié)可以知道另一個(gè)節(jié)的地址。在對(duì)某個(gè)節(jié)內(nèi)存地址作改變之后,只要能保證節(jié)之間正確的指向關(guān)系,程序依舊能正常運(yùn)行。
在動(dòng)態(tài)鏈接器初始化階段,鏈接器解析ELF文件的程序頭表,獲取程序的動(dòng)態(tài)節(jié)所在地址,保存到自己的鏈接映射結(jié)構(gòu)link_map中。然后解析動(dòng)態(tài)節(jié),得到GOT節(jié)所在地址,改寫(xiě)GOT節(jié)的第1項(xiàng)為link_map的開(kāi)始地址,第2項(xiàng)為符號(hào)解析函數(shù)_dl_runtime_resolve()的入口地址。在程序運(yùn)行階段,當(dāng)程序需要調(diào)用某庫(kù)函數(shù),通過(guò)對(duì)應(yīng)的PLT完成對(duì)GOT的代碼引用。ELF中各節(jié)的指向關(guān)系及使用時(shí)段如圖3所示。
2.2防御方法的有效性
GOT地址隨機(jī)化之后,需要保證新的GOT地址不能被攻擊者輕易獲取到。除了保證新的GOT地址是隨機(jī)的之外,還需要防止攻擊者能夠通過(guò)讀取固定地址內(nèi)存中的數(shù)據(jù)計(jì)算出GOT所在的地址。經(jīng)分析,主要存在以下兩種獲取途徑:讀取PLT中代碼或者通過(guò)讀取指向GOT的節(jié)。
讀取PLT的代碼,即通過(guò)讀取PLT所在地址的數(shù)據(jù),通過(guò)反匯編,獲取GOT的地址。假設(shè)第n個(gè)外部函數(shù)fn在GOT中的地址0x0804a004,那么PLTn中第1條指令jmp *0x0804a004對(duì)應(yīng)的機(jī)器碼為FF 25 04 A0 04 08,因此攻擊者只需要讀取PLTn的前6個(gè)字節(jié),通過(guò)反匯編就可以獲取fn在GOT中的地址。如果想讓攻擊者無(wú)法通過(guò)反匯編代碼得到引用的地址,引用Intel處理器的段寄存器是最好的選擇。
Intel處理器中一共有6個(gè)段寄存器:CS、DS、ES、SS、FS、GS,其中:CS為代碼段的基地址,DS和ES為數(shù)據(jù)段的基地址,SS為堆棧段的基地址,F(xiàn)S和GS用于特殊目的的基地址。假設(shè)引用的段寄存器為FS,對(duì)應(yīng)的段的基地址設(shè)置為0x08040000,那么PLTn中第1條指令將為jmp *fs:0xa004,對(duì)應(yīng)的機(jī)器碼為64 FF 25 04 A0 00 00,在不知道FS寄存器基地址的情況下,將不會(huì)知道GOT所在地址。而FS寄存器的基地址是在內(nèi)核中進(jìn)行設(shè)置,在用戶(hù)態(tài)沒(méi)有直接方法可以得到。
讀取指向GOT的節(jié)是通過(guò)ELF的程序頭表、動(dòng)態(tài)節(jié)和GOT節(jié)的數(shù)據(jù)指向關(guān)系,只要其中任意一個(gè)在內(nèi)存中地址是固定的,就可以通過(guò)信息泄露,依次向下解析,直到獲取到GOT節(jié)的地址。因?yàn)閮H僅在動(dòng)態(tài)鏈接器初始化階段才會(huì)根據(jù)程序頭表得到動(dòng)態(tài)節(jié)地址。故在動(dòng)態(tài)鏈接器初始化完畢之后,修改程序頭表中的對(duì)應(yīng)項(xiàng),清除程序頭表中的動(dòng)態(tài)段信息。而動(dòng)態(tài)節(jié)和GOT節(jié)可以同時(shí)加載到隨機(jī)內(nèi)存地址中。
所以,為了保證GOT地址隨機(jī)化的有效性,GOT修改后ELF各節(jié)的隨機(jī)情況及指向關(guān)系如圖4所示,其中灰色部分的節(jié)都被加載到隨機(jī)內(nèi)存。PLT通過(guò)段寄存器實(shí)現(xiàn)對(duì)GOT的間接引用。在動(dòng)態(tài)鏈接器初始化后,清除程序頭表中的相關(guān)項(xiàng),而動(dòng)態(tài)節(jié)和GOT節(jié)均加載到隨機(jī)的內(nèi)存地址中。這樣攻擊者就無(wú)法通過(guò)上述的兩種途徑計(jì)算出GOT所在內(nèi)存地址。
3GOTRand的實(shí)現(xiàn)
本文通過(guò)修改Linux內(nèi)核代碼實(shí)現(xiàn)GOTRand保護(hù)方法的原型系統(tǒng)。GOTRand的總體框架如圖5所示,其中在加載時(shí),通過(guò)定制加載器將GOT加載到隨機(jī)內(nèi)存,并引入段寄存器;在動(dòng)態(tài)鏈接器初始化完畢之后,清除程序頭表中關(guān)于動(dòng)態(tài)段的信息。內(nèi)核對(duì)ELF程序的加載函數(shù)為load_elf_binary()。通過(guò)修改load_elf_binary()函數(shù)實(shí)現(xiàn)定制加載器,在定制加載器中主要增加ELF節(jié)信息的獲取、GOT內(nèi)存地址隨機(jī)和段寄存器的引入3個(gè)模塊。
3.1GOT地址的隨機(jī)
GOT地址隨機(jī)主要是將GOT節(jié)和動(dòng)態(tài)節(jié)加載到隨機(jī)的內(nèi)存地址。動(dòng)態(tài)節(jié)中的數(shù)據(jù)不需要進(jìn)行修改,因此只需要給予只讀權(quán)限。GOT節(jié)中數(shù)據(jù)需要在符號(hào)解析完成之后將函數(shù)的真正地址寫(xiě)入GOT中,因此需要有可讀可寫(xiě)權(quán)限。根據(jù)兩個(gè)節(jié)的內(nèi)存屬性的不同,申請(qǐng)兩頁(yè)隨機(jī)的空閑頁(yè):只讀頁(yè)和可讀可寫(xiě)頁(yè)。動(dòng)態(tài)節(jié)加載到只讀頁(yè)中,GOT節(jié)加載到可讀可寫(xiě)中。
進(jìn)程虛擬地址空間預(yù)留了多個(gè)空洞。其中在32位程序中,程序的加載基地址通常為0x08048000,0x08048000地址之下的內(nèi)存空間通常都不會(huì)被使用到,但是0x08048000以下的內(nèi)存也不是全部都能夠使用的。Linux內(nèi)核為了防御空指針解引用漏洞,引入了mmap_min_addr機(jī)制[12],不允許小于mmap_min_addr值的地址映射內(nèi)存。mmap_min_addr的值可以由用戶(hù)配置,在默認(rèn)的Linux發(fā)行版中,通常設(shè)置為65536,即低64MB內(nèi)存不能使用。所以選擇在mmap_min_addr到0x08048000地址隨機(jī)申請(qǐng)兩頁(yè)空間,如圖6所示。
3.2段寄存器的引入
通過(guò)分析當(dāng)前Linux系統(tǒng)對(duì)段寄存器的使用情況,發(fā)現(xiàn)在32位程序中,CS、DS、ES、SS用作基本的段寄存器使用,其基地址均設(shè)置為0,GS用于指向線(xiàn)程局部存儲(chǔ)(Thread Local Storage, TLS)區(qū)域,而FS寄存器一般沒(méi)有。在64位程序中,CS、DS、ES、SS寄存器的基地址在硬件上被強(qiáng)制為0值,段基地址僅對(duì)FS和GS寄存器來(lái)說(shuō)才有意義,F(xiàn)S被用于指向線(xiàn)程局部存儲(chǔ)(TLS)區(qū)域,而GS寄存器沒(méi)有被使用。所以,在當(dāng)前Linux系統(tǒng)的實(shí)現(xiàn)中,無(wú)論是32位還是64位程序,都剛好有一個(gè)空閑未用的段寄存器,剛好可以被用于GOTRand中。在有了空閑段寄存器后,隨機(jī)地為其設(shè)置一個(gè)段寄存器基地址,然后對(duì)PLT節(jié)代碼進(jìn)行補(bǔ)丁,對(duì)GOT使用新的段寄存器進(jìn)行訪問(wèn)。
3.3動(dòng)態(tài)段信息的清除
在動(dòng)態(tài)鏈接器初始化完畢之后,程序會(huì)默認(rèn)跳轉(zhuǎn)到可執(zhí)行程序入口點(diǎn)開(kāi)始執(zhí)行。這里需要對(duì)動(dòng)態(tài)段信息進(jìn)行清除,因此需要在鏈接器初始化完畢之后,需要內(nèi)核接管程序的控制權(quán)。通過(guò)對(duì)動(dòng)態(tài)鏈接器初始化部分代碼的分析,發(fā)現(xiàn)程序?qū)OT的第一次寫(xiě)操作為向GOT的第1項(xiàng)寫(xiě)入自己的鏈接映射結(jié)構(gòu)link_map的地址。而link_map結(jié)構(gòu)建立好之后,鏈接器已經(jīng)不需要通過(guò)程序頭表中動(dòng)態(tài)段的信息。根據(jù)鏈接器的這個(gè)特性,采用寫(xiě)保護(hù)的方法來(lái)獲取程序的控制權(quán)。在內(nèi)核加載ELF程序時(shí)將GOT所在的內(nèi)存頁(yè)屬性標(biāo)記為不可寫(xiě)。當(dāng)動(dòng)態(tài)鏈接器初始化過(guò)程中向GOT進(jìn)行寫(xiě)操作的時(shí)候,將會(huì)導(dǎo)致處理器產(chǎn)生頁(yè)故障(Page Fault)異常,將會(huì)執(zhí)行內(nèi)核的頁(yè)故障處理函數(shù),從而內(nèi)核控制了程序的控制權(quán)。
按照現(xiàn)有Linux內(nèi)核的頁(yè)故障處理流程,對(duì)GOT的寫(xiě)入異常將會(huì)被判定為用戶(hù)態(tài)的非法訪問(wèn)操作,從而進(jìn)行非法訪問(wèn)頁(yè)故障處理。在非法訪問(wèn)頁(yè)故障處理中通過(guò)判斷CR2寄存器中保存的異常虛擬地址是否為該進(jìn)程的GOT的第1項(xiàng);同時(shí)根據(jù)異常錯(cuò)誤代碼的W/R位判斷是否為寫(xiě)異常,可以判定動(dòng)態(tài)鏈接器初始化是否完畢。如果動(dòng)態(tài)鏈接器初始化完畢,則清除程序頭表中的動(dòng)態(tài)段信息;同時(shí)將GOT所在內(nèi)存標(biāo)記為可讀可寫(xiě)。
4測(cè)試
在Debian GNU/Linux 6 i686發(fā)行版上通過(guò)一個(gè)已知漏洞的攻擊實(shí)驗(yàn),驗(yàn)證了GOTRand的防御效果,并從理論上比較了幾種已有保護(hù)方法的防御效果。另外,通過(guò)使用SPEC CPU2006測(cè)試機(jī)對(duì)GOTRand進(jìn)行性能測(cè)試。結(jié)果顯示,GOTRand不僅能有效防御GOT解引用和GOT覆寫(xiě)攻擊,而且性能損耗很低。
4.1防御效果測(cè)試
實(shí)驗(yàn)選擇了一個(gè)公開(kāi)了漏洞利用程序的漏洞程序進(jìn)行測(cè)試。選擇的漏洞程序?yàn)镹ginx HTTP服務(wù)器,對(duì)應(yīng)的漏洞號(hào)為CVE20132028[13]。在Nginx HTTP服務(wù)器1.3.91.4.0版本的程序中,在ngx_http_parse_chunked()函數(shù)中存在整型溢出漏洞。在metasploit的模塊中,有對(duì)該漏洞進(jìn)行完美利用的利用程序[14]。
經(jīng)過(guò)測(cè)試,metasploit的利用程序能夠在默認(rèn)的debian發(fā)行版中成功地獲取shell,但是,在GOTRand系統(tǒng)中,不能成功獲取shell。
分析該漏洞利用程序,發(fā)現(xiàn)該利用程序使用的Return Oriented Programming(ROP)[15]鏈中使用GOT解引用的方法繞過(guò)ASLR,其中假定了localtime_r函數(shù)在GOT中的地址默認(rèn)為0x080b4128,如圖7所示,但是在GOTRand中GOT加載到隨機(jī)地址,所以讀取到的地址0x080B4128中的內(nèi)容并不是函數(shù)localtime_r的地址,整個(gè)漏洞利用也就失敗。
本文還比較了SecGOT和Full RELRO對(duì)于GOT解引用的防御效果。SecGOT在動(dòng)態(tài)鏈接器初始化時(shí),對(duì)GOT地址進(jìn)行了隨機(jī);但是攻擊者可以先對(duì)PLT進(jìn)行解引用,即可得到GOT所在地址,再對(duì)GOT進(jìn)行解引用,因此只需要構(gòu)造一個(gè)更加復(fù)雜一點(diǎn)的ROP[12]鏈即可成功利用。GOT解引用只涉及到GOT的讀操作,因此Full RELRO完全沒(méi)有防御效果。
對(duì)于GOT覆寫(xiě)劫持程序控制流方法,需要知道GOT所在地址并且具有可寫(xiě)權(quán)限。在SecGOT中,GOT所在地址可以間接得到,因此不能防御GOT覆寫(xiě)攻擊。在Full RELRO中,GOT不可改寫(xiě),因此不能進(jìn)行GOT覆寫(xiě)。而在GOTRand中,因?yàn)槎胃綦x機(jī)制,沒(méi)有方法能獲取GOT所在地址,因此也不能進(jìn)行GOT覆寫(xiě)。3種保護(hù)方法的防御效果及是否需要對(duì)程序進(jìn)行重新編譯對(duì)比結(jié)果如表1所示。
4.2性能測(cè)試
實(shí)驗(yàn)選用SPEC CPU2006測(cè)試集[16]進(jìn)行測(cè)試。因?yàn)镾ecGOT未公布其相關(guān)代碼或者工具,沒(méi)法對(duì)其進(jìn)行測(cè)試。所以這里只測(cè)試比較了Full RELRO和GOTRand運(yùn)行的額外開(kāi)銷(xiāo),結(jié)果如表2所示。通過(guò)測(cè)試集中的12個(gè)測(cè)試程序測(cè)試發(fā)現(xiàn),GOTRand增加的運(yùn)行開(kāi)銷(xiāo)極小,平均只有0.0029s,遠(yuǎn)小于Full RELRO的額外開(kāi)銷(xiāo)。
5結(jié)語(yǔ)
在現(xiàn)有的Linux系統(tǒng)中,GOT解引用和GOT覆寫(xiě)是兩種常用的漏洞利用方法。通過(guò)GOT解引用,可以獲取GOT中庫(kù)函數(shù)的真正地址,從而繞過(guò)地址空間布局隨機(jī)化的保護(hù)機(jī)制;通過(guò)GOT覆寫(xiě),可以劫持程序的控制流程。本文提出了一種基于地址隨機(jī)和段隔離的全局偏移表保護(hù)方法,通過(guò)將動(dòng)態(tài)節(jié)和GOT節(jié)均加載到隨機(jī)內(nèi)存中,同時(shí)對(duì)全局偏移表的代碼引用使用段隔離保護(hù),很好地保護(hù)了全局偏移表中的函數(shù)指針,能夠有效地緩解針對(duì)全局偏移表的漏洞利用。因?yàn)槎渭拇嫫魇荌ntel處理器所特有的寄存器,所以該方法只適用于Intel架構(gòu)的ELF程序的全局偏移表保護(hù)。下一步將其他處理器的架構(gòu)進(jìn)行研究,提出更加通用的保護(hù)方法。
參考文獻(xiàn):
[1]
TEAM PAX. PaX address space layout randomization [EB/OL]. [20030315]. https://pax.grsecurity.net/docs/aslr.txt.
[2]
Wikipedia. Data execution prevention [EB/OL]. [20150312]. https://en.wikipedia.org/wiki/Data_Execution_Prevention.
[3]
MARCOGISBERT H, RIPOLL I. On the effectiveness of fullASLR on 64bit Linux [EB/OL]. [20151120]. http://cybersecurity.upv.es/attacks/offset2lib/offset2libpaper.pdf.
[4]
ROGLIA G F, MARTIGNONI L, PALEARI R, et al. Surgically returning to randomized lib(c) [C]// ACSAC09: Proceedings of the 2009 Annual Computer Security Applications Conference. Piscataway, NJ: IEEE, 2009: 60-69.
[5]
Open Security Group. How to hijack the global offset table with pointers for root shells [EB/OL]. [20150404]. http://www.opensecurity.org/texts/6.
[6]
DAVI L, SADEGHI A R, LEHMANN D, et al. Stitching the gadgets: on the ineffectiveness of coarsegrained controlflow integrity protection [C]// SEC14: Proceedings of the 23rd USENIX Security Symposium. Berkeley, CA: USENIX Association, 2014: 401-416.
[7]
KLEIN T. A Bug Hunters Diary: a Guided Tour Through the Wilds of Software Security [M]. San Francisco: No Starch Press, 2011:183-185.
[8]
KLEIN T. RELROA (not so well known) memory corruption mitigation technique [EB/OL]. [20150221]. http://tkblog.blogspot.jp/2009/02/relronotsowellknownmemory.html.
[9]
ZHANG C, DUAN L, WEI T, et al. SecGOT: secure global offset tables in ELF executables [C]// Proceedings of the 2013 International Conference on Computer Science and Electronics Engineering. Amsterdam: Atlantis Press, 2013: 995-998.
[10]
XU J, KALBARCZYK Z, IYER R K. Transparent runtime randomization for security [C]// Proceedings of the 22nd International Symposium on Reliable Distributed Systems. Piscataway, NJ: IEEE, 2003: 260-269.
[11]
Tool Interface Standards Committee. Executable and Linkable Format (ELF) [EB/OL]. [20150401]. http://www.cs.cmu.edu/afs/cs/academic/class/15213f00/docs/elf.pdf.
[12]
ARGYROUDIS P, GLYNOS D. Protecting the core: kernel exploitation mitigations [EB/OL]. [20150517]. http://census.gr/media/bheu2011wp.pdf.
[13]
CVE Details. Vulnerability details: CVE20132028 [EB/OL]. [20130719]. http://www.cvedetails.com/cve/20132028.
[14]
MACMANUS G, HAL, SAELO. Nginx HTTP Server 1.3.91.4.0 chunked encoding stack buffer overflow [EB/OL]. [20151024]. http://www.rapid7.com/db/modules/exploit/linux/http/nginx_chunked_size.
[15]
ROEMER R, BUCHANAN E, SHACHAM H, et al. Returnoriented programming: systems, languages, and applications [J]. ACM Transactions on Information and System Security, 2012, 15(1): Article No. 2.
[16]
HENNING J L. SPEC CPU2006 benchmark descriptions [J]. ACM SIGARCH Computer Architecture News, 2006, 34(4): 1-17.