亚洲免费av电影一区二区三区,日韩爱爱视频,51精品视频一区二区三区,91视频爱爱,日韩欧美在线播放视频,中文字幕少妇AV,亚洲电影中文字幕,久久久久亚洲av成人网址,久久综合视频网站,国产在线不卡免费播放

        ?

        Linux二進(jìn)制漏洞利用
        ——突破系統(tǒng)防御的關(guān)鍵技術(shù)

        2018-09-25 07:56:16曾永瑞
        信息安全研究 2018年9期
        關(guān)鍵詞:指針內(nèi)核調(diào)用

        曾永瑞 李 喆

        (北京天融信網(wǎng)絡(luò)安全技術(shù)有限公司阿爾法實驗室 北京 100085) (zeng_yongrui@topsec.com.cn)

        近年來,隨著攻防技術(shù)不斷發(fā)展,二進(jìn)制漏洞相關(guān)的資料也越來越多,但國內(nèi)的環(huán)境導(dǎo)致了目前大家對Windows系統(tǒng)上的二進(jìn)制漏洞有更多的關(guān)注,多數(shù)介紹二進(jìn)制漏洞的書籍資料都是基于Windows平臺的,而對于Linux二進(jìn)制漏洞的研究的相關(guān)資料只能在網(wǎng)絡(luò)上一些個人博客、論壇中找到,缺乏有效的總結(jié)和整理, 也沒能很好地引起人們的重視.本文的目的就是對Linux平臺上的二進(jìn)制漏洞利用作一個淺顯的梳理.

        本文完成了以下幾個方面的工作:

        1) 介紹了目前Linux系統(tǒng)上常見的二進(jìn)制漏洞類型以及其基本原理.

        2) 整理了這些漏洞經(jīng)典的利用方法、相關(guān)的文獻(xiàn)資料;接著,介紹了Linux系統(tǒng)中針對這些利用方法而出現(xiàn)的安全機制;最后,深入介紹了幾個目前繞過這些安全機制的方法.

        3) 總結(jié)了文中提到的漏洞特點以及共性, 并針對它們的本質(zhì)特征提出進(jìn)一步的防護(hù)方案.

        1 常見的Linux二進(jìn)制漏洞

        1.1 棧溢出漏洞

        緩沖區(qū)溢出攻擊的概念最早可以追溯到20世紀(jì)70年代,但直到1996年,AlphaOne[1]才首次公開展示了棧緩沖區(qū)溢出漏洞的利用原理,并提出了“shellcode”這一概念.

        若程序在接受用戶輸入時,不對輸入數(shù)據(jù)進(jìn)行邊界檢查,直接將其保存到棧上,且寫入目標(biāo)數(shù)據(jù)結(jié)構(gòu)的數(shù)據(jù)大小超過為該結(jié)構(gòu)分配的內(nèi)存大小時,會發(fā)生棧緩沖區(qū)溢出.這將導(dǎo)致棧上相鄰數(shù)據(jù)的損壞,通常在錯誤觸發(fā)溢出的情況下,會導(dǎo)致程序崩潰.但需要注意的是,棧包含有函數(shù)調(diào)用的返回地址,在現(xiàn)在主流的各種緩解措施沒有出現(xiàn)之前,攻擊者只需簡單地將可執(zhí)行代碼注入正在運行的程序緩沖區(qū)中,再將返回地址覆蓋為指向注入代碼的地址,就能輕易獲取未經(jīng)授權(quán)系統(tǒng)的訪問權(quán)限.

        即便到了今天,存在各種緩解措施的情況下,每年緩沖區(qū)溢出漏洞在各種類型漏洞中所占比例一直都是居高不下,所以棧溢出漏洞依然值得警惕.

        1.2 堆漏洞

        相對于棧而言,堆內(nèi)存的管理機制要復(fù)雜得多,在各種系統(tǒng)上的實現(xiàn)也不相同,甚至不同平臺中堆內(nèi)存管理器也有不同的實現(xiàn),例如dlmalloc,ptmalloc,tcmalloc,jemalloc等等,甚至有些程序還會使用自己創(chuàng)建的內(nèi)存池來管理內(nèi)存.

        1.2.1堆溢出

        堆溢出的原理和棧溢出類似,當(dāng)程序向堆塊(chunk)中寫入的數(shù)據(jù)超過了堆塊本身可使用的字節(jié)數(shù)時,溢出的數(shù)據(jù)將會覆蓋到物理相鄰的下一個堆塊.

        1999年,w00w00安全小組的Conover[2]首次詳細(xì)介紹了堆溢出的原理和利用方式,從這時起,漏洞利用的目標(biāo)逐漸擴(kuò)大到了堆上.

        1.2.2釋放重引用漏洞

        釋放重引用漏洞UAF(use after free)如其字面意思,當(dāng)一個內(nèi)存塊被釋放之后,再次使用指向這塊內(nèi)存的指針?biāo)l(fā)的漏洞.

        許多程序中,內(nèi)存被分配以用于存儲對象實例.這些對象使用完后,程序會釋放分配的內(nèi)存,以節(jié)省系統(tǒng)資源.然后,需要將指向該對象的指針設(shè)為NULL,如果一個指針沒有指向適當(dāng)類型的有效對象,則稱這類指針為“懸掛指針”(dangling pointer).通常來說導(dǎo)致“懸掛指針”有如下2個原因:

        1) 程序利用了已被釋放的C++對象,從而訪問無效的內(nèi)存位置;

        2) 一個程序返回了指向它的本地變量的指針,因為這個變量只在該函數(shù)內(nèi)部有效,一旦函數(shù)結(jié)束,這個指針將變?yōu)橐粋€無效的指針.

        在某些情況下,程序可能會使用指向已被釋放對象的指針.如果發(fā)生這種情況,程序?qū)⑦M(jìn)入意外的執(zhí)行流程,這可能導(dǎo)致程序崩潰或甚至更危險的后果,有關(guān)UAF漏洞的利用方法,將在2.3節(jié)介紹.

        1.2.3雙重釋放漏洞

        雙重釋放(double free)[3]漏洞本質(zhì)上可以算是UAF漏洞的一個子集,即對1塊內(nèi)存釋放2次,這會產(chǎn)生不確定的后果.

        雙重釋放漏洞的利用原理也很好理解:堆塊釋放后,物理相鄰的前、后堆塊若為空閑狀態(tài),會進(jìn)行合并操作,然后利用Unlink機制將該空閑堆塊從(unsorted bin)中取下.如果用戶精心構(gòu)造的假堆塊被Unlink,很容易導(dǎo)致一次固定地址寫,然后轉(zhuǎn)換為任意地址讀寫,從而控制程序的執(zhí)行.

        1.3 整數(shù)溢出漏洞

        C語言中存在3種基本的整型數(shù)據(jù)類型——short,int和long,這3種類型又可分為有符號(signed)和無符號(unsigned),每種數(shù)據(jù)類型都有各自的大小范圍[4].但是對有符號類型和無符號類型的區(qū)分只在編譯器層面,底層匯編指令處理的只是二進(jìn)制數(shù)據(jù).當(dāng)程序中的數(shù)據(jù)超過其數(shù)據(jù)類型的范圍,則會造成整數(shù)溢出.這種溢出本身不會造成任意代碼執(zhí)行,但卻可能繞過程序的邊界檢查,從而間接地導(dǎo)致?;蚨训木彌_區(qū)溢出,如圖1所示:

        圖1 一個整數(shù)溢出漏洞的例子

        上述代碼第4行中的strlen()的返回類型是size_t(unsigned int),其返回值存儲在unsigned char(范圍是0~255)數(shù)據(jù)類型中.因此,任何大于unsigned char的表示范圍的值都會導(dǎo)致整數(shù)溢出.當(dāng)用戶輸入的密碼長度在260~264 B之間時,變量passwd_len實際上為4~8,繞過了第5行的邊界檢查,進(jìn)而導(dǎo)致了一個棧的緩沖區(qū)溢出漏洞.

        1.4 格式化字符串漏洞

        格式化字符串函數(shù)是一種特別的函數(shù),它可以傳入可變數(shù)量的參數(shù),并將第1個參數(shù)作為格式化字符串,來解析之后的參數(shù).通俗來說,格式化字符串函數(shù)就是將計算機內(nèi)存中表示的數(shù)據(jù)轉(zhuǎn)化為人類可讀的字符串格式.幾乎所有的CC++程序都會利用這類函數(shù)來輸出信息,或處理字符串.

        關(guān)于格式化字符串漏洞的原理,可以先看看下面這條語句:

        printf(″Color %s, Number %d, Float %4.2f″).

        這條語句中沒有為格式化字符串提供參數(shù),程序依然可以編譯成功并正常運行,但會將棧上格式化字符串地址上面的3個變量分別解析為:

        1) 其地址對應(yīng)的字符串;

        2) 其內(nèi)容對應(yīng)的整型值;

        3) 其內(nèi)容對應(yīng)的浮點值.

        對于2)和3)來說并沒有太大的問題,但是對于1)來說,如果提供了一個不可訪問地址,程序就會因此而崩潰.通過格式化字符串,用戶可以使用%s,%x從棧輸出數(shù)據(jù);也可以用%n向任意地址寫入數(shù)據(jù),這就造成了內(nèi)存泄露的問題.表1中列出了常見的幾種格式化字符串函數(shù).

        表1 常見輸出格式化字符串函數(shù)

        1.5 競爭條件漏洞

        競爭條件(race condition)[5]是指多個線程或進(jìn)程在讀寫1個共享數(shù)據(jù)時結(jié)果依賴于它們執(zhí)行的相對時間.競爭條件發(fā)生在多個進(jìn)程或者線程讀寫數(shù)據(jù)時,其最終的結(jié)果依賴于多個進(jìn)程的指令執(zhí)行順序.由于目前的系統(tǒng)中大量采用并發(fā)編程,經(jīng)常對資源進(jìn)行共享,往往會產(chǎn)生競爭條件漏洞.而且由于在并發(fā)時,執(zhí)行流的不確定性很大,競爭相對難察覺,并且在漏洞的復(fù)現(xiàn)和調(diào)試方面會比較困難.這給修復(fù)競爭條件漏洞也帶來了不小的困難.

        2016年Linux內(nèi)核內(nèi)存子系統(tǒng)在處理寫入時復(fù)制COW(copy-on-write)產(chǎn)生的競爭條件漏洞,可以說是近年來最有名的競爭條件漏洞.這個被稱為“臟?!?DirtyCow)的漏洞在發(fā)現(xiàn)時已經(jīng)存在于Linux內(nèi)核9年之久,可見競爭條件漏洞的隱蔽性.

        2 傳統(tǒng)利用手段和技巧

        堆和棧中的漏洞曾經(jīng)乃至現(xiàn)在都是二進(jìn)制漏洞中所占比例最大的,而整數(shù)溢出漏洞最終實現(xiàn)利用,也是通過間接轉(zhuǎn)化為堆棧溢出漏洞.所以本節(jié)主要介紹在各種漏洞緩解措施未普及之前,棧溢出漏洞和堆相關(guān)漏洞的經(jīng)典利用方法.

        2.1 面向?qū)蚓幊?/h3>

        最古老的棧溢出漏洞利用,只需簡單地將函數(shù)的返回地址覆蓋為需要執(zhí)行的shellcode的地址即可,隨著不可執(zhí)行位NX(no-execute)[6]技術(shù)的應(yīng)用,直接向棧或者堆上直接注入shellcode的方式難以繼續(xù)發(fā)揮效果.直到2007年,加州大學(xué)圣迭戈分校的Shacham[7]在其論文中提出了面向?qū)蚓幊蘎OP(return oriented programming)技術(shù),其主要思想是在棧緩沖區(qū)溢出的基礎(chǔ)上,依靠借用程序中多個以返回指令結(jié)尾的代碼塊(gadgets),組成1個ROP鏈,它可以實現(xiàn)任何邏輯功能,從而控制程序的執(zhí)行流程,其原理如圖2所示:

        圖2 ROP技術(shù)原理

        ROP技術(shù)是圖靈完備的,換句話說,它為攻擊者提供了一種功能齊全的“編程語言”,可以使用它來執(zhí)行任何所需的操作.此外,gadget可以選擇的位置和利用方式也多種多樣,表2中列出了一些Linux下常見的ROP技術(shù):

        表2 常見的ROP技術(shù)

        2.2 堆溢出的利用

        關(guān)于堆漏洞利用的傳統(tǒng)方法,可以參考Phantasmagoria[8]于2005年提出的5種堆漏洞利用方法,他將這些方法命名為“The House of xxx”,具體如下:

        1) The House of Prime;

        2) The House of Mind;

        3) The House of Force;

        4) The House of Lore;

        5) The House of Spirit.

        這幾種堆溢出利用的首要思路就是通過覆蓋物理相鄰的下一堆塊的元數(shù)據(jù)來破壞堆的數(shù)據(jù)結(jié)構(gòu),進(jìn)而執(zhí)行惡意代碼.然而隨著ASLR等技術(shù)的出現(xiàn),文中所提到的方法在大多數(shù)情況下都無法應(yīng)用,但是現(xiàn)如今又出現(xiàn)了一系列新的名為“The House of xxx”的利用方法,和文獻(xiàn)[8]中所提到的方法已有較大的不同.

        2.3 UAF漏洞利用

        關(guān)于UAF漏洞的利用,Watchfire的安全研究人員Afek等人[9]在2007年的Black Hat USA大會上,結(jié)合一個Microsoft IIS 6服務(wù)器的漏洞,完整地講述了UAF漏洞的原理和利用技巧.

        UAF最常用的利用方式就是通過申請與重用對象大小相等的堆塊,使惡意數(shù)據(jù)被分配到已釋放對象的內(nèi)存位置,從而覆蓋舊對象的內(nèi)存空間.

        了解編譯器實現(xiàn)對象的方式對于能夠使用適當(dāng)?shù)臄?shù)據(jù)覆蓋原始對象至關(guān)重要.以32位程序的UAF漏洞為例,一個C++對象開頭是一個指向虛函數(shù)表的指針,如圖3所示.

        若將惡意數(shù)據(jù)的第1個DWORD大小的內(nèi)容設(shè)置為包含一個特殊地址,該地址將取代對象的虛函數(shù)表.內(nèi)存的其余部分布置為將要執(zhí)行的shellcode.當(dāng)使用call [eax+offset]執(zhí)行虛函數(shù)調(diào)用時,再將程序的執(zhí)行流程轉(zhuǎn)移到shellcode中.整個過程的原理如圖4所示.

        圖3 對象虛函數(shù)的實現(xiàn)方式

        圖4 UAF漏洞利用的最常見方式

        2.4 堆噴射

        堆噴射(heap spray)技術(shù)的出現(xiàn)最早可以追溯到2001年,奧地利著名安全小組TESO發(fā)布的一個針對BSD telnet服務(wù)器攻擊程序中[10],首次利用了堆噴射技術(shù).當(dāng)時該技術(shù)并沒有確切的名稱,其目的也只是為了提供一個穩(wěn)定的存放shellcode的地方,然后在棧溢出劫持返回地址進(jìn)行跳轉(zhuǎn).

        隨著后來ASLR技術(shù)的出現(xiàn),這個古老技術(shù)又成為了輔助繞過ASLR的絕佳手段.尤其是對于一些能內(nèi)嵌執(zhí)行腳本的程序,為攻擊者提供了動態(tài)分配內(nèi)存的途徑,對于不同的程序來說往往有如下這些堆噴射方法:

        1) 利用JavaScript進(jìn)行堆噴射;

        2) 利用ActionScript進(jìn)行堆噴射;

        3) 利用HTML5進(jìn)行堆噴射;

        4) 利用VBScript進(jìn)行堆噴射;

        5) 直接將堆噴射數(shù)據(jù)構(gòu)造進(jìn)文件中,例如圖片、視頻等.

        3 現(xiàn)代防護(hù)措施

        3.1 應(yīng)用級加固措施

        3.1.1地址空間布局隨機化

        在第2節(jié)的一些漏洞利用方法中,最后都要將程序流程指向內(nèi)存中已布置好的shellcode的地址,為了防止這些內(nèi)存損壞漏洞,地址空間布局隨機化(address space layout randomization, ASLR)[11]技術(shù)應(yīng)運而生.

        為了防止攻擊者每次都能可靠地跳轉(zhuǎn)到內(nèi)存中特定的地址,ASLR隨機排列進(jìn)程的關(guān)鍵數(shù)據(jù)區(qū)域的地址.

        3.1.2不可執(zhí)行位

        計算機將指令當(dāng)成數(shù)據(jù)的概念,使得匯編語言、編譯器與其他自動編程工具得以實現(xiàn),但也造成一些缺陷,緩存溢出就是一個典型例子.NX技術(shù)的出現(xiàn),就是為了彌補這一缺陷,用于區(qū)分內(nèi)存中指令集與數(shù)據(jù).任何標(biāo)記了NX位的區(qū)塊代表僅供存儲數(shù)據(jù)使用而不是存儲處理器的指令集,處理器不會將此處的數(shù)據(jù)作為代碼執(zhí)行,這種技術(shù)可防止多數(shù)的緩存溢出攻擊.

        3.2 編譯器加固措施

        3.2.1位置無關(guān)可執(zhí)行程序

        前面提到的ASLR是操作系統(tǒng)的功能選項,作用于可執(zhí)行文件裝入內(nèi)存運行時,因而只能隨機化stack,heap和libraries的基址;而位置無關(guān)可執(zhí)行程序(position independent executables, PIE)[12]是編譯器的功能選項(-fPIE),作用于可執(zhí)行文件的編譯過程,其隨機化了可行性文件裝載內(nèi)存的基址(代碼段,PLT,GOT,數(shù)據(jù)段等共同的基址).

        PIE需要在源代碼級別遵循一套特定的語義,并且需要編譯器的支持.使用了絕對內(nèi)存地址的指令,會被替換為相對尋址指令.這些間接處理過程可能導(dǎo)致PIE的運行效率下降,但是因為大多數(shù)處理器對位置無關(guān)可執(zhí)行程序都有很好的支持,使得這一點點效率的下降基本可以忽略.

        3.2.2重定位只讀

        要理解重定位只讀(relocation read-only, RELRO)[13],首先需要了解ELF文件的動態(tài)鏈接過程.一個程序在引用了某個模塊中的函數(shù)時,因為不知道模塊加載位置,需要將相關(guān)代碼地址抽出,放在數(shù)據(jù)段中的全局偏移表(global offset table, GOT)中.

        例如調(diào)用func函數(shù),假設(shè)該函數(shù)定義在glibc共享庫中,若要找到該函數(shù)的地址,鏈接器需要生成一段額外的代碼,放入代碼段中一個名為過程鏈接表(procedure link table, PLT)的位置,通過這段代碼獲取func函數(shù)地址,并完成對它的調(diào)用.其過程如圖5所示.

        圖5 ELF文件動態(tài)鏈接過程

        由于GOT表是可寫的,假設(shè)攻擊者得到了一個任意地址寫入的機會,把GOT表中的函數(shù)地址覆蓋為shellcode地址,在程序進(jìn)行調(diào)用這個函數(shù)時就會執(zhí)行shellcode.而開啟RELRO后,可以在程序解析符號時,將此過程中使用的重要數(shù)據(jù)結(jié)構(gòu)標(biāo)記為只讀,從而防止攻擊者修改這些重要結(jié)構(gòu).

        RELRO又可以分為部分重定位只讀(partial RELRO)和完全重定位只讀(full RELRO)2種模式.這2種模式最大的區(qū)別在于,前者GOT表是可寫的,而后者GOT表是只讀的,但是因為Full RELRO嚴(yán)重影響了程序運行的性能,所以一般只在重要的程序中才會開啟.

        3.2.3Canary

        Canary[14]是一種用于緩解緩沖區(qū)溢出的安全機制,這個名稱源于曾經(jīng)礦井中用來預(yù)警瓦斯氣體的金絲雀(Canary),因為金絲雀瓦斯氣體十分敏感,當(dāng)瓦斯含量超過一定限度,人類還毫無察覺時,金絲雀卻早已毒發(fā)身亡.

        同樣的道理,在棧上返回地址之前添加一個Canary值,函數(shù)返回時檢查該值有沒有被改變,便可知道是否發(fā)生了溢出.在GCC中,通過-fstack-protector選項和-fstack-protector-all選項以支持該功能.

        圖6 TLS結(jié)構(gòu)

        以x64平臺為例,Canary是從fs:0x28偏移位置獲取的,fs寄存器用于存放線程局部存儲( thread local storage, TLS)信息,該結(jié)構(gòu)在Glibc中的實現(xiàn)如圖6所示:

        Canary值由glibc產(chǎn)生并保存在tcbhead_t結(jié)構(gòu)中,程序返回時,將棧上的Canary與該結(jié)構(gòu)中保存的值比較,當(dāng)檢查失敗時,執(zhí)行g(shù)libc的__stack_chk_fail函數(shù),并終止進(jìn)程.

        3.2.4FORTIFY_SOURCE

        該技術(shù)源于2004年由RedHat的工程師提交的一個GCC和glibc補丁[15],其目的是提供一種輕量級的緩沖區(qū)溢出和格式化字符串漏洞防護(hù)機制 .它可以通過編譯時定義FORTIFY_SOURCE標(biāo)志來配置,在目前主流的Linux發(fā)行版甚至安卓平臺中都能夠見到它的身影.

        對內(nèi)存拷貝型函數(shù),在用戶調(diào)用過程中,F(xiàn)ORTIFY_SOURCE將對圖7中幾種行為進(jìn)行判定:

        圖7 FORTIFY_SOURCE的4種判斷方式

        1) 正確,不需要在編譯或運行時檢查.

        2) 編譯器不知道實際復(fù)制進(jìn)buf中數(shù)據(jù)的長度,于是將此類不安全的函數(shù)替換為相對安全的__memcpy_chk和__strcpy_chk函數(shù),如果發(fā)生溢出,就會調(diào)用內(nèi)置的chk_fail ()函數(shù),如圖8所示:

        圖8 glibc-2.24中__memcpy_chk的實現(xiàn)

        3) 編譯器在編譯的過程中會檢測到溢出.

        4) 在此類調(diào)用的方式下,編譯器無從得知緩沖區(qū)的長度,在編譯時不作檢查,運行時無法檢查,這種調(diào)用往往可能導(dǎo)致緩沖區(qū)的溢出.GCC中可以通過設(shè)置D_FORTIFY_SOURCE選項為1或2這2種不同的級別,前者認(rèn)為錯,而后者認(rèn)為安全.

        上述4類是FORTIFY_SOURCE對內(nèi)存拷貝類函數(shù)的判斷標(biāo)準(zhǔn).

        此外,F(xiàn)ORTIFY_ SOURCE還有針對格式化字符串的保護(hù),glibc中的printf等格式化字符串函數(shù)默認(rèn)可以使用%n參數(shù),并且能夠任意指定格式化串的參數(shù),例如%4$p,在FORTIFY_SOURCE=2的編譯條件下,glibc啟動了FORTIFY_SOURCE的相關(guān)保護(hù).glibc在調(diào)用printf時,更改為調(diào)用__printf_chk函數(shù),如圖9所示:

        圖9 glibc-2.24中___printf_chk的實現(xiàn)

        3.3 系統(tǒng)級加固措施

        3.3.1內(nèi)核地址空間布局隨機化

        內(nèi)核地址空間布局隨機化(kernel address space layout randomization, KASLR),顧名思義也就是內(nèi)核地址的隨機化,這項技術(shù)將在開機引導(dǎo)時將內(nèi)核代碼加載到隨機位置,在Linux內(nèi)核3.14版本中引入了該特性.

        3.3.2內(nèi)核頁表隔離

        內(nèi)核頁表隔離(kernel page-table isolation, KPTI)是Linux內(nèi)核中的一種安全技術(shù),它將現(xiàn)在被用戶空間和內(nèi)核空間共享使用的這張表分成2部分,內(nèi)核空間和用戶空間各自使用1個,從而解決頁表泄露的問題.

        3.3.3管理模式訪問保護(hù)管理模式執(zhí)行保護(hù)

        在很多內(nèi)核漏洞的利用過程中,通常會將內(nèi)核指針重定向到用戶空間,這種利用方式被稱為ret2usr.為了抵御這種攻擊,管理模式訪問保護(hù)(supervisor mode access prevention, SMAP)和管理模式執(zhí)行保護(hù)(supervisor mode execution prevention, SMEP)被提出.兩者的作用分別是禁止內(nèi)核訪問用戶空間的數(shù)據(jù)、禁止內(nèi)核執(zhí)行用戶空間的代碼.Linux內(nèi)核從3.0開始支持SMEP,從3.7開始支持SMAP.

        4 現(xiàn)代利用手段

        4.1 SROP方法

        SROP(sigreturn oriented programming)這種方法由阿姆斯特丹自由大學(xué)的Bosman等人[16]提出,該技術(shù)利用了Linux系統(tǒng)信號處理機制存在一個設(shè)計缺陷.和傳統(tǒng)的ROP攻擊相比顯得更加簡單、可靠、可移植.

        了解Linux的信號處理機制是使用SROP技術(shù)的前提,這里可以參考圖10,簡要地了解一下Linux信號處理機制:

        圖10 Linux信號處理機制

        當(dāng)有中斷或異常產(chǎn)生時,內(nèi)核向進(jìn)程發(fā)出一個Signal,此時進(jìn)程被掛起,系統(tǒng)切換到內(nèi)核態(tài).內(nèi)核執(zhí)行do_signal()函數(shù),并且最終調(diào)用setup_frame()函數(shù),向用戶棧中push一個保存有全部寄存器的值和Signal信息(定義在名為sigcontext的結(jié)構(gòu)中),另外還會push一個sigruturn()系統(tǒng)調(diào)用的地址.此時的用戶棧布局如圖11所示.

        圖11 setup_frame()調(diào)用后用戶棧

        其中User Context和Signal Info這2部分被稱為Signal Frame.之后,跳轉(zhuǎn)到注冊過的Signal handler中處理相應(yīng)的Signal.Signal handler返回后,內(nèi)核執(zhí)行sigreturn系統(tǒng)調(diào)用,為該進(jìn)程恢復(fù)之前保存的上下文,其中包括將所有壓入的寄存器,重新pop回對應(yīng)的寄存器,最后恢復(fù)進(jìn)程的執(zhí)行.

        觀察上面信號處理的流程,可以發(fā)現(xiàn)主要的變動都在Signal Frame中.而Signal Frame是保存在用戶的地址空間中,所以用戶是可以讀寫的.

        由于內(nèi)核不會去保存這個Signal對應(yīng)的Signal Frame,所以當(dāng)執(zhí)行sigreturn系統(tǒng)調(diào)用時,此時的Signal Frame并不一定是之前內(nèi)核為用戶進(jìn)程保存的Signal Frame.到這里SROP技術(shù)的基本思想一目了然,它通過控制調(diào)用堆棧,將偽造的sigcontext結(jié)構(gòu)置于調(diào)用棧上,當(dāng)執(zhí)行完sigreturn,偽造的sigcontext結(jié)構(gòu)內(nèi)容被恢復(fù)到寄存器中,便可控制程序流程.一個最簡單的例子如圖12所示.

        2) 將rax設(shè)置為execve的系統(tǒng)調(diào)用號.

        3) 將rip設(shè)置為syscalll指令的地址.

        sigreturn系統(tǒng)調(diào)用將這些值恢復(fù)相應(yīng)寄存器,最后恢復(fù)進(jìn)程執(zhí)行時,將會得到一個shell.

        如果需要執(zhí)行一系列的函數(shù),就像構(gòu)造一個ROP鏈一樣,只需要作2處修改即可:

        1) 修改棧指針指向下一個偽造的sigcontext.

        2) 將程序指針設(shè)置為syscall;ret這個指令序列的地址,如圖13所示.

        SROP通常只需要一個gadget即可成功實施此攻擊,使得這種攻擊變得簡單而有效,在文獻(xiàn)[16]中,作者還給出了“syscall; ret”這個gadget在不同內(nèi)核版本中出現(xiàn)的位置,有興趣的讀者可以去自行查閱.

        圖12 偽造的sigcontext結(jié)構(gòu)

        圖13 SROP鏈

        4.2 Blind ROP

        Blind ROP技術(shù)由斯坦福大學(xué)的Bittau等人[17]提出,該技術(shù)可以在沒有二進(jìn)制程序和源碼的情況下同時繞過NX,ASLR和Canary的安全保護(hù),但必須符合以下條件:

        1) 目標(biāo)程序存在棧溢出漏洞;

        2) 目標(biāo)程序進(jìn)程在崩潰之后會重新啟動,且進(jìn)程加載基址與原來相同,即使用fork重新創(chuàng)建子進(jìn)程,但未采用execve執(zhí)行磁盤上的程序(fork-only without execve).

        BROP的主要思想就是首先通過不斷的枚舉,得到棧上正確的Canary,然后枚舉出可用的Gadgets來構(gòu)造write系統(tǒng)調(diào)用、遠(yuǎn)程dump內(nèi)存,最終實現(xiàn)漏洞利用,具體過程下面將詳細(xì)介紹.

        1) 暴力枚舉

        不斷增大輸入緩沖區(qū)數(shù)據(jù)的長度,直到發(fā)現(xiàn)目標(biāo)程序剛好崩潰,得到Canary之前??臻g的長度.

        2) Stack Reading

        因為Canary的變化只是在每個字節(jié)上,所以文獻(xiàn)[17]中提出了一種名為Stack Reading的方法來快速枚舉出正確的Canary值,原理如圖14所示:

        圖14 通過Stack Reading 枚舉出正確的Canary

        首先只覆蓋Canary的第1個字節(jié),然后從0x00到0xFF枚舉,當(dāng)枚舉到一個正確的數(shù)值時,服務(wù)器進(jìn)程并不會崩潰,記錄下這個字節(jié),繼續(xù)覆蓋第2個字節(jié),然后不斷重復(fù)前面的過程,直到將Canary逐字節(jié)全部枚舉出來.

        0x00到0xFF有256種可能,所以在32位系統(tǒng)中,最多需要嘗試4×256=1 024次,64位中最多需要嘗試8×256=2 048次,整個過程只需幾秒.

        3) 尋找Stop Gadgets

        接下來需要找到構(gòu)造ROP鏈,從遠(yuǎn)程dump漏洞程序的內(nèi)存.文獻(xiàn)[17]提出了Stop Gadget這一概念,它尋找其他Gadgets取到了至關(guān)重要的作用.為了找到這種Gadgets,需要將返回地址覆蓋為某個代碼段的地址,然后通過不斷枚舉尋找(代碼段的地址可以在上一步Stack Reading中獲得,對于沒有PIE的程序也可以從可執(zhí)行文件默認(rèn)的加載基址開始),當(dāng)程序的執(zhí)行流跳到這時,程序并不會崩潰,而是進(jìn)入了無限循環(huán),攻擊者能一直保持連接狀態(tài).

        4) 尋找Useful Gadgets

        接下來,需要找到其他具有某些功能而不是會造成Crash的Gadget.這類Gadgets稱為“Useful Gadgets”.

        同樣還是采用上一步枚舉的方法,將返回地址覆蓋為某個代碼段的地址,返回地址之后填充多個Stop Gadgets,如圖15所示.

        當(dāng)正在枚舉的地址是一個無效的Gadget時,程序?qū)罎?,如圖16所示.

        但是如果是一個有效的Gadget,程序?qū)⑦M(jìn)入一個無限循環(huán)的狀態(tài),如圖17所示.

        以上是尋找Useful Gadgets的原理,而要從遠(yuǎn)程dump內(nèi)存,可以通過構(gòu)造write(int sock, void *buf, int len)來實現(xiàn),接下來的關(guān)鍵就是如何找到相關(guān)的Gadgets.構(gòu)造這個調(diào)用的4個Gadgets可以在圖18所示的位置找到.

        圖15 枚舉有效的Gadgets

        圖16 無效的Gadget導(dǎo)致程序崩潰

        圖17 有效的Gadget使程序保持運行狀態(tài)

        圖18 通過Stack Reading 枚舉出正確的Canary

        在這之后,便可以通過dump下的內(nèi)存,構(gòu)造漏洞利用程序.

        4.3 Stack Pivot

        Stack Pivot[18]出現(xiàn)的時間已經(jīng)很久了,但到目前為止,一直是漏洞利用中比較重要的輔助技術(shù).目的是將棧劫持到一個攻擊者能夠控制的內(nèi)存上去,在該位置再進(jìn)行ROP.

        假設(shè)攻擊者控制了棧上部分區(qū)域,但是中間有一段不可控制的內(nèi)存,這時攻擊者需要控制棧指針跳轉(zhuǎn)到可控部分,繼續(xù)執(zhí)行ROP指令,圖19只是使用該技術(shù)的最簡單情況,要想劫持棧指針還有很多方法,任何可以修改棧指針的Gadget都可以用于Stack Pivot.

        圖19 Stack Pivot

        4.4 繞過full RELRO

        在第4節(jié)中曾提到過,對于partial RELRO的情況,GOT表仍然是可寫的,仍可以進(jìn)行GOT表覆寫,所以本節(jié)中將重點介紹繞過full RELRO的方法[19],此外這里假設(shè)讀者已了解Linux的動態(tài)重定位原理,就不再對其進(jìn)行詳細(xì)介紹了.

        當(dāng)使用full RELRO時,所有的重定位將在加載時完成,GOT表被設(shè)置只讀,不會有惰性解析(lazy binding)的過程,并且link_map結(jié)構(gòu)的地址和_dl_runtime_resolve地址也不會初始化.在.dynamic段中的Elf_Dyn結(jié)構(gòu)中,有一個DT_DEBUG條目,它的值是程序加載時,由動態(tài)加載器設(shè)置好的,指向堆中保存的一個r_debug類型的數(shù)據(jù)結(jié)構(gòu).此外,該結(jié)構(gòu)的r_map域保存著一個指向link_map鏈表的指針,因此可以通過這個結(jié)構(gòu)來恢復(fù)link_map的值,如圖20所示.

        圖20 從DT_DEBUG條目恢復(fù)link_map

        得到link_map的位置后,需要偽造一個重定位項(因為.got.plt是只讀的).為此需要覆蓋掉原來l_info結(jié)構(gòu)的DT_JMPREL域的內(nèi)容,使其指向一個偽造的動態(tài)條目,而這個動態(tài)條目則指向一個重定位項.這個重定位項引用了已經(jīng)存在的函數(shù)符號,而r_offset則指向一塊可寫的內(nèi)存區(qū)域,如圖21所示.

        圖21 覆蓋DT_JMPREL偽造動態(tài)條目

        接著,還需要恢復(fù)_dl_runtime_resolve函數(shù)的指針,因為GOT表中已經(jīng)沒有_dl_runtime_resolve函數(shù)的指針了.解引用l_info域中的第1個link_map結(jié)構(gòu)取得描述第1個共享庫的link_map,而這個共享庫是不被完全RELRO保護(hù)的.攻擊者通過l_info[DT_PLTGOT]域來得到對應(yīng)的動態(tài)條目(右側(cè)的.dynamic),接著是.plt.got段(總是在右側(cè)),其中的第2個條目里就有_dl_runtime_resolve的地址,如圖22所示:

        圖22 _dl_runtime_resolve

        最后,將link_map結(jié)構(gòu)作為第1個參數(shù),將一個新的.dynsym偏移作為第2個參數(shù),就可以調(diào)用_dl_runtime_resolve函數(shù)了.但這里存在一個問題問題——_dl_runtime_resolve不僅會調(diào)用目標(biāo)函數(shù),還會嘗試將目標(biāo)函數(shù)的地址寫到正確的GOT項中,但因為GOT是不可寫的,程序會因此崩潰.為了解決這個問題,將原本指向.rel.dyn段的DT_JMPREL指向攻擊者控制的一塊內(nèi)存區(qū)域,并在那塊位置偽造一個Elf_Rel結(jié)構(gòu),且其r_offset域指向一塊可寫的內(nèi)存區(qū)域,其r_info指向目標(biāo)符號.所以,當(dāng)一個庫被解析時,它的地址將會被寫到一個可寫的位置,程序就不會崩潰,而且請求的函數(shù)也將會被執(zhí)行.

        5 總 結(jié)

        近幾年,二進(jìn)制漏洞分析與利用技術(shù)已經(jīng)發(fā)展得相當(dāng)成熟,很多技術(shù)也被黑產(chǎn)所利用,也正因如此,軟件安全領(lǐng)域得到了極大的發(fā)展,對個人終端、服務(wù)器的攻擊越來越困難.從上面介紹的利用方法來看,雖然有能繞過各種安全機制的途徑,但往往利用條件都有一些限制.如果程序開啟了全部安全機制(NX,PIE,ASLR,F(xiàn)ull RELRO等),那么就需要通過泄露地址等方式才能完成利用.

        所以未來的二進(jìn)制漏洞的發(fā)展趨勢,可能會逐漸向其他方面轉(zhuǎn)移.例如卡巴斯基實驗室最近發(fā)布報告指出,近幾年來,路由器等網(wǎng)絡(luò)設(shè)備已成為高級持續(xù)性威脅(APT)常用的攻擊渠道,結(jié)合目前的行業(yè)趨勢,筆者預(yù)測未來Linux相關(guān)二進(jìn)制攻防博弈主要集中在下面3個領(lǐng)域.

        1) 移動終端

        移動互聯(lián)網(wǎng)時代早已到來,移動終端上每年發(fā)現(xiàn)的漏洞正在呈倍增長.特別是基于Linux的Android系統(tǒng),有很多Linux內(nèi)核漏洞也會影響到它.而對于iOS系統(tǒng)漏洞,其漏洞數(shù)量也是保持持續(xù)上升趨勢.雖然由于iOS的封閉性和相關(guān)安全研究者較少,但是隨著這幾年相關(guān)安全書籍和文章增加,iOS設(shè)備的漏洞也會越來越多.

        2) 物聯(lián)網(wǎng)設(shè)備

        物聯(lián)網(wǎng)的誕生,勢必將改變?nèi)藗兾磥淼纳?,根?jù)相關(guān)估算,到2020年,物聯(lián)網(wǎng)設(shè)備的數(shù)量將會超過200億.此外根據(jù)統(tǒng)計,暴露在公網(wǎng)上的物聯(lián)網(wǎng)設(shè)備中,大部分都是使用Linux操作系統(tǒng),根據(jù)目前相關(guān)資料以及近年來出現(xiàn)的與物聯(lián)網(wǎng)設(shè)備相關(guān)的蠕蟲病毒信息,針對物聯(lián)網(wǎng)設(shè)備的攻擊手段及技術(shù)已經(jīng)很成熟.這些攻擊手段與傳統(tǒng)安全攻擊手段類似,但更偏重于系統(tǒng)底層.同時由于物聯(lián)網(wǎng)設(shè)備的系統(tǒng)特殊性和封閉性,都對這種攻擊提供了很好的保護(hù)作用.

        相對其他領(lǐng)域而言,物聯(lián)網(wǎng)可以算是才剛剛起步,物聯(lián)網(wǎng)設(shè)備的安全更是沒有引起很多廠商的重視.作為和人們生活息息相關(guān)的物品,如果物聯(lián)網(wǎng)產(chǎn)品存在安全問題,那就有可能直接影響到個人財產(chǎn)安全,甚至人身安全.例如曾經(jīng)Black Hat上展示的關(guān)于心臟起搏器、胰島素泵(注射胰島素的設(shè)備,當(dāng)注入過量時可導(dǎo)致患者昏迷)的入侵等等.

        3) 云計算平臺

        云計算平臺的架構(gòu)可以簡單地分為軟件即服務(wù)(SaaS)、平臺即服務(wù)(PaaS)、基礎(chǔ)設(shè)施即服務(wù)(IaaS),它們分別為用戶提供了應(yīng)用軟件、系統(tǒng)平臺和IT基礎(chǔ)設(shè)施資源等.

        在SaaS層上,傳統(tǒng)的Web漏洞、軟件漏洞都可能會出現(xiàn),而此層的漏洞風(fēng)險更大,也是外部最容易觸及到的.

        在PaaS層上,由于大多數(shù)服務(wù)器采用Linux系統(tǒng),Linux上的Web服務(wù)器漏洞、系統(tǒng)提權(quán)等漏洞依然需要人們重視.

        在IaaS層上,則存在虛擬機漏洞、數(shù)據(jù)存儲缺陷等安全問題.如果利用虛擬機逃逸漏洞,進(jìn)而控制云平臺主系統(tǒng),那么造成的后果也是不堪設(shè)想的.

        猜你喜歡
        指針內(nèi)核調(diào)用
        萬物皆可IP的時代,我們當(dāng)夯實的IP內(nèi)核是什么?
        強化『高新』內(nèi)核 打造農(nóng)業(yè)『硅谷』
        核電項目物項調(diào)用管理的應(yīng)用研究
        偷指針的人
        娃娃畫報(2019年5期)2019-06-17 16:58:10
        基于嵌入式Linux內(nèi)核的自恢復(fù)設(shè)計
        Linux內(nèi)核mmap保護(hù)機制研究
        LabWindows/CVI下基于ActiveX技術(shù)的Excel調(diào)用
        為什么表的指針都按照順時針方向轉(zhuǎn)動
        基于系統(tǒng)調(diào)用的惡意軟件檢測技術(shù)研究
        基于改進(jìn)Hough變換和BP網(wǎng)絡(luò)的指針儀表識別
        電測與儀表(2015年5期)2015-04-09 11:30:42
        色狠狠色狠狠综合一区| 亚洲国产中文字幕视频| 亚洲国产美女精品久久久久∴| 色伦专区97中文字幕| 亚洲成av人在线观看无堂无码 | 熟妇人妻av无码一区二区三区| 亚洲AV无码久久精品成人| 精品在线亚洲一区二区三区 | 9l国产自产一区二区三区| 日本免费视频| 亚洲熟少妇在线播放999| 亚洲国产成人AⅤ片在线观看| 亚洲一区视频中文字幕| 日产乱码一二三区别免费l| 亚洲av日韩av综合| 亚洲av影院一区二区三区四区| 老司机在线免费视频亚洲| 国产99久久久国产精品~~牛| 乱人伦视频中文字幕| 国产在线视频h| 日韩精品免费av一区二区三区 | 国产成人高清精品亚洲一区| 青青草成人在线免费视频| 国产在线精品一区二区在线看| 精品一区二区av天堂| 亚洲精品综合久久中文字幕| 三个男吃我奶头一边一个视频| 久久精品无码中文字幕| jk制服黑色丝袜喷水视频国产| 一区二区三区视频亚洲| 国产精品爽爽v在线观看无码| 久久久久久久久久久熟女AV| 国产大学生自拍三级视频| 天堂视频在线观看一二区| 色五月丁香五月综合五月4438| 91精品91| 日韩精品一区二区亚洲观看av| 国产伦人人人人人人性| 四虎永久在线精品免费观看地址| 中文字幕日韩一区二区不卡| 久久99精品久久久久婷婷|