官术网_书友最值得收藏!

3.2 Windows安全漏洞保護分析

微軟等大型軟件廠商為了最大程度地保護系統安全運行,逐漸在操作系統中增加了多種保護機制,致力于減少系統程序漏洞,以及漏洞被觸發和利用的可能性。本節主要介紹Windows平臺下幾種典型的漏洞利用阻斷技術,包括/GS、DEP、ASLR及SafeSEH等,同時本節對這些技術的不足也進行了分析,最后對微軟為緩解操作系統漏洞被利用而推出的EMET工具進行簡要介紹。

3.2.1 棧溢出檢測選項/GS

1./GS保護機制

Visual Studio 2003中加入了/GS棧溢出檢測這個編譯選項,微軟命名為Stack Canary(棧金絲雀)。金絲雀對空氣中的甲烷和一氧化碳濃度的高敏感度使它成為最早的煤礦安全報警器,這里是指,調用函數時將一個隨機生成的秘密值存放在棧上,當函數返回時,檢查這個堆棧檢測儀的值是否被修改,以此判斷是否發生了棧溢出。

/GS棧溢出檢測選項最初在Visual Studio 2003中默認情況下是關閉的。自Visual Studio 2005以后的版本中,微軟將/GS選項改為默認開啟,也可以在系統中對其進行禁用設置。如圖3-31所示,在Visual Studio 2013中新建一個項目后,可以選擇菜單中的“項目”→“項目屬性”→“配置屬性”→“C/C++”→“代碼生成”→“安全檢查”找到該選項。

如果編譯器啟用了/GS選項,那么當程序編譯時,它首先會計算出程序的一個安全Cookie(偽隨機數,4字節DWORD無符號整型);然后將安全Cookie保存在加載模塊的數據區中,在調用函數時,這個Cookie被復制到棧中,位于RET返回地址、EBP與局部變量之間,如圖3-31所示;在函數調用結束時,程序會把這個Cookie和事先保存的Cookie進行比較。如果不相等,就說明進程的系統棧被破壞,需要終止程序運行。

在典型的緩沖區溢出中,棧上的返回地址會被數據所覆蓋(如圖3-32所示),但在返回地址被覆蓋之前,安全Cookie早己經被覆蓋了,因此在函數調用結束時檢查Cookie會發現異常,并終止程序,這將導致漏洞利用的失效。

圖3-31 /GS編譯選項設置

圖3-32 使用/GS選項編譯的程序的棧幀結構

/GS保護機制除了在棧中加入安全Cookie之外,在Visual Studio 2008及以后的版本中還增加了對函數內部的局部變量和參數的保護功能,編譯器會進行以下操作。

●對函數棧重新排序,把字符串緩沖區分配在棧幀的高地址上,這樣當字符串緩沖區被溢出時,也就不能溢出任何本地局部變量了。

●將函數參數復制到寄存器或放到棧緩沖區上,以防止參數被溢出。

2.對抗/GS保護

從/GS棧溢出檢測機制來看,其關鍵之處就是在棧中加入安全Cookie來保護相關參數和變量,所以對抗這種棧溢出保護機制的直接方法是圍繞Cookie值展開的。

(1)猜測Cookie值

Skape曾經在文獻Reducing the Effective Entropy of GS Cookies中討論并證明了/GS保護機制使用了幾個較弱的熵源,攻擊者可以對其進行計算并使用它們來預測(或猜測)Cookie值。但是這種方法只適用于針對本地系統的攻擊。

(2)通過同時替換棧中的Cookie和Cookie副本

替換加載模塊數據區中的Cookie值(它必須是可寫的,否則程序就無法在運行中動態更新Cookie),同時用相同的值替換棧中的Cookie,以此來繞過棧上的Cookie保護。

(3)覆蓋SEH繞過Cookie檢查

/GS保護機制并沒有保護存放在棧上的SEH結構。因此,如果能夠寫入足夠的數據來覆蓋SEH記錄,并在Cookie檢查之前觸發異常,那么可以控制程序的執行流程。該方法相當于是利用SEH進行漏洞攻擊。雖然有SEH保護機制SafeSEH,但SafeSEH也是可以被繞過的,因而可以同時繞過/GS保護機制。

(4)覆蓋父函數的棧數據繞過Cookie檢查

當函數的參數是對象指針或結構指針時,這些對象或結構存在于調用者的堆棧中,這種情況下可能導致/GS保護被繞過:覆蓋對象的虛函數表指針,將虛函數重定向到需要執行的惡意代碼,那么如果在檢查Cookie前存在對該虛函數的調用,則可以觸發惡意代碼的執行。

3.2.2 數據執行保護DEP

1.數據執行保護DEP(Data Execution Prevention)機制

棧溢出漏洞的最常見利用方式是:在棧中精心構造二進制串溢出原有數據結構,進而改寫函數返回地址,使其跳轉到位于棧中的Shellcode執行。如果使棧上數據不可執行,那么就可以阻止這種漏洞利用方式的成功實施。而DEP就是通過使可寫內存不可執行或使可執行內存不可寫,以消除類似威脅的。

DEP是微軟隨Windows XP SP2和Windows 2003 SP1的發布而引入的一種數據執行保護機制。類似DEP這樣的內存保護方式較早就出現了,但是叫法不盡相同,較為通用的稱呼是NX,即No eXecute。此外,Intel把它這種技術稱為Execute Disable或XD-bit;AMD把它稱為Enhanced Virus Protection,也寫成W^X,意思就是可寫或可執行,但二者絕不允許同時發生。

事實上,不可執行堆棧技術并不新鮮,早在多年前,SUN公司(已被甲骨文公司收購)的Solaris操作系統中就提供了啟用不可執行棧的選項,這要早于Windows的DEP技術。早在1993年,NT 3.1系統里就有了VirtualProtect函數的使用,在內存頁中包含了是否可執行的標志,但是由于當時的處理器不支持對每個內存頁上的數據進行不可執行檢查,所以這種標志因缺乏硬件支持而實際上并未發揮作用。

2003年9月,AMD率先為不可執行內存頁提供了硬件級的支持,即NX的特性;隨后Intel也提供了類似的被稱為XD(eXecute Disable)的特性。在硬件支持的基礎上,微軟開始在Windows系統上真正引入了DEP保護機制。

DEP在具體實現上有兩種模式:硬件實現和軟件實現。如果CPU支持內存頁NX屬性,就是硬件支持的DEP。如果CPU不支持,那就是軟件支持的DEP模式,這種DEP不能直接組織在數據頁上執行代碼,但可以防止其他形式的漏洞利用,如SEH覆蓋。Windows中的DEP tabsheet會表明是否支持硬件DEP。

根據操作系統和Service Pack版本的不同,DEP對軟件的保護行為是不同的。在Windows的早期版本及客戶端版本中,只為Windows核心進程啟用了DEP,但此設置已在新版本中改變。

在Windows服務器操作系統上,除了那些手動添加到排除列表中的進程外,系統為其他所有進程都開啟了DEP保護,而客戶端操作系統使用了可選擇啟用的方式。微軟的這種做法很容易理解:客戶端操作系統通常需要能夠運行各種軟件,而有的軟件可能和DEP不兼容;在服務器上,在部署到服務器前都經過了嚴格的測試(如果確實是不兼容,仍然可以把它們放到排除名單中)。

此外,Visual Studio編譯器提供了一個鏈接標志(/NXCOMPAT),可以在生成目標應用程序時使程序啟用DEP保護。

2.對抗數據執行保護DEP

DEP技術使得在棧上或其他一些內存區域執行代碼成為不可能,但是執行已經加載的模塊中的指令或調用系統函數則不受DEP影響,而棧上的數據只需作為這些函數/指令的參數即可。從已有的技術來看,要繞過DEP保護可以有以下幾種選擇。

●利用ret-to-libc執行命令或進行API調用,如調用WinExec實現執行程序。

●將包含Shellcode的內存頁面標記為可執行,然后再跳過去執行。

●通過分配可執行內存,再將Shellcode復制到內存區域,然后跳過去執行。

●先嘗試關閉當前進程的DEP保護,然后再運行Shellcode。

3.2.3 地址空間布局隨機化ASLR

1.地址空間布局隨機化ASLR機制

從Windows Vista開始,微軟向其新版本操作系統中引入了地址空間布局隨機化(Address Space Layout Randomization,ASLR)保護機制。其原理很簡單:通過對堆、棧和共享庫映射等線性區域布局的隨機化,增加攻擊者預測目的地址的難度,防止攻擊者直接定位攻擊代碼位置,達到阻止漏洞利用的目的。例如,同一版本的Windows XP上系統里DLL模塊的加載地址是固定的,那么攻擊者只需針對不同操作系統版本進行分別處理即可,但是使用ASLR之后,攻擊者必須在攻擊代碼中進行額外的地址定位操作,才有可能成功利用漏洞,這在一定程度上確保了系統安全。

ASLR保護機制進行隨機化的對象主要包括以下幾個方面。

1)映像隨機化:改變可執行文件和DLL文件的加載地址。

2)棧隨機化:改變每個線程棧的起始地址。

3)堆隨機化:改變已分配堆的基地址。

對于地址空間布局隨機化ASLR機制,微軟從可執行程序編譯時的編譯器選項和操作系統加載時地址變化兩個方面進行了實現和完善。

在Visual Studio 2005 SP 1及更高版本的Visual Studio編譯器中,均提供了連接選項/DYNAMICBASE。使用了該連接選項之后,編譯后的程序每次運行時,其內部的棧等結構的地址都會被隨機化。

2.ASLR機制的缺陷和繞過方法

(1)對本地攻擊者無能為力

系統每次重啟,ASLR就會在整個系統中生效。如果使用了特定DLL的所有進程都卸載該DLL,那么在下次加載時它能被加載到新的隨機地址,但是,如果系統中的DLL總是由多個進程加載,導致只有在操作系統重啟時才能再次隨機化。

因此,雖然ASLR對于來自網絡的攻擊,比如像蠕蟲之類的攻擊行為都能很好地防止,可是,對于在本地計算機的攻擊卻顯得無能為力。對于本地攻擊,攻擊者很容易獲得所需要的地址。

(2)造成內存碎片的增多

ASLR的運行時間越長,其帶來的內存碎片也會越多,如果不及時進行清理,有可能會影響系統的效率,特殊情況下甚至會降低系統的穩定性。

當然,為了減少虛擬地址空間的碎片,操作系統把隨機加載庫文件的地址空間限制為8位,即地址空間為256,而且隨機化發生在地址前兩個有意義的字節上。

例如,對于地址:0x12345678,其存儲方式如圖3-33所示。

圖3-33 地址存儲方式

當啟用了ASRL技術后,只有4 3和2 1是隨機化的。在某些情況下,攻擊者可以利用或者觸發任意代碼:當利用一個允許覆蓋棧里返回地址的漏洞時,原來固定的返回地址被系統放在棧中;而如果啟用ASLR,則地址被隨機處理后才放入棧中,比如返回地址是0x12345678(0x1234是被隨機部分,5678始終不變)。如果可以在0x1234XXXX(1234是隨機的,并且操作系統已經把它們放在棧中了)空間中找到有用的跳轉指令,如JMP ESP等,則只需要用這些找到的跳轉指令的地址的低字節替換棧中的低字節即可,該方法也稱為返回地址部分覆蓋法。

(3)利用沒有采用/DYNAMICBASE選項保護的模塊作跳板

當前很多程序和DLL模塊未采用/DYNAMICBASE連接選項進行分發,這就導致即使系統每次重啟,也并非對所有應用程序地址空間分布都進行了隨機化,仍然有模塊的基地址沒有發生變化。利用程序中沒有啟用ASLR的模塊中的相關指令作為跳板,使得這些跳轉指令的地址在重啟前后一致,故用該地址來覆蓋異常處理函數指針或返回地址即可繞過ASLR。

3.2.4 安全結構化異常處理SafeSEH

1.SafeSEH機制

為了防止SEH機制被攻擊者惡意利用,微軟通過在.Net編譯器中加入/SafeSEH連接選項,從而正式引入了SafeSEH技術。

SafeSEH的實現原理較為簡單,就是編譯器在鏈接生成二進制IMAGE時,把所有合法的異常處理函數的地址解析出來制成一張安全的SEH表,保存在程序的IMAGE數據塊里面,當程序調用異常處理函數時會將函數地址與安全SEH表中的地址進行匹配,檢查調用的異常處理函數是否位于該表中。如果IMAGE不支持SafeSEH,則表的地址為0。

安全結構化異常處理(Safe Structured Exception Handling,SafeSEH)保護機制的作用是防止覆蓋和使用存儲棧上的SEH結構。如果使用/SafeSEH鏈接器選項編譯和鏈接一個程序,那么對應二進制的頭部將包含一個由所有合法異常處理程序組成的表,當調用異常處理程序時會檢查這張表,以確保所需的處理程序在這張表中。這項檢查工作是作為ntdll.dll中的RtlDispatchException例程的一部分來完成的,它會執行以下測試。

●確保異常記錄位于當前線程的棧上。

●確保處理程序的指針沒有指回棧。

●確保處理程序已經在經授權處理程序列表中登記。

●確保處理程序位于可執行的內存映像中。

由此可以看出,SafeSEH保護機制對于保護異常處理程序而言相當有效,但稍后將看到,它也并非絕對安全。

2.對抗SafeSEH機制的方法

SafeSEH是一種非常有效的漏洞利用防護機制,如果一個進程加載的所有模塊都支持SafeSEH的IMAGE,覆蓋SafeSEH進行漏洞利用就基本不可能。Windows 7下絕大部分的系統庫都支持SafeSEH的IMAGE,但Windows XP/2003等絕大部分系統庫不支持Windows的IMAGE。當進程中存在一個不支持SafeSEH的IMAGE時,整個SafeSEH的機制就很有可能失效。此外,由于支持SafeSEH需要.Net的編譯器支持,現在仍有大量的第三方程序和庫未使用.Net編譯或者未采用/safeSEH鏈接選項,這就使得繞過SafeSEH成為可能。

(1)利用未啟用SafeSEH的模塊作為跳板進行繞過

對于目前的大部分Windows操作系統,其系統模塊都受SafeSEH保護,可以選用未開啟SafeSEH保護的模塊來利用,比如漏洞軟件本身自帶的dll文件。在這些模塊中尋找特定的某些跳轉指令如pop/POP/ret等,用其地址進行SEH函數指針的覆蓋,使得SEH函數被重定位到這些跳轉指令,由于這些指令位于加載模塊的IMAGE空間內,且所在模塊不支持SHE,因此異常被觸發時,可以執行到這些指令,通過合理安排shellcode,那么就有可能繞過SafeSEH機制,執行shellcode中的功能代碼。

(2)利用加載模塊之外的地址進行繞過

利用加載模塊之外的地址進行繞過,包括從堆中進行繞過和從其他一些特定內存繞過。從堆中繞過,源于這樣的缺陷:如果SEH中的異常處理函數指針指向堆區,則通常可以執行該異常處理函數,因此只需將shellcode布置到堆區就可以直接跳轉執行。此外,如果在進程內存空間中的一些特定的、不屬于加載模塊的內存中找到跳轉指令,則仍然可以用這些跳轉指令的地址來覆蓋異常處理函數的指針,從而繞過SafeSEH。

3.2.5 增強緩解體驗工具包EMET

1.EMET機制

增強緩解體驗工具包(Enhanced Mitigation Experience Toolkit,EMET)是微軟推出的一套用來緩解漏洞攻擊、提高應用軟件安全性的增強型體驗工具。與前面幾種保護機制不同,EMET并不隨Windows操作系統一起發布或預裝,而是用戶可自行選擇安裝,通過配置可實現對指定應用的增強型保護,但由于操作系統版本的差異性,不同版本的操作系統上所能提供的增強型保護機制也不盡相同,且目前僅支持Windows XP SP3及以上版本。

目前,微軟官網提供EMET 5.5版本的下載(http://www.microsoft.com/emet),不過2018年7月31日以后,微軟將不再提供該工具的更新支持,微軟建議使用安全性更強的Windows 10系統。

EMET的基本保護功能介紹如下。

(1)增強型DEP

自Windows XP SP3起,操作系統內建支持DEP,但對于特定應用程序而言,則還與生成時所使用的編譯連接選項有關,同時還需要結合OPT-in和OPT-out的配置來使DEP生效。而EMET則能夠通過在指定應用中強制調用SetProcessPolicy來打開DEP保護,使其生效。

(2)SafeSEH的升級版——SEHOP

SEHOP正是看到了SafeSEH被繞過的可能性,從而增加的一項針對目標程序的運行時防護方案——在分發異常處理函數前,動態檢驗SEH鏈的完整性。需要說明的是:SEHOP技術在較新的操作系統中已經內建支持了,EMET對于這些版本的操作系統則更多的是一個完善和增強。

(3)強制性ASLR

在前面針對ASLR的介紹中已經提及,ASLR的防護能力的有效性和程序生成時是否采用/DYNAMICBASE連接選項有關,因此EMET對此進行了增強——EMET能夠對生成時未使用/DYNAMICBASE連接選項的模塊進行加載基址的強制隨機化。實現思路則是對于那些動態加載的模塊或延遲載入的模塊,強制占用其首選基址,從而迫使DLL模塊選擇其他基址通過重定位的方式實現模塊加載。

(4)HeapSpray防護

在前面的章節中,對HeapSpray攻擊進行了介紹,針對這種很重要的攻擊方式,EMET通過采用強制分配內存、占用常用攻擊地址的方式來迫使HeapSpray攻擊中的內存分配失效,從而挫敗攻擊。

【案例3】Windows安全漏洞保護技術應用

體驗微軟目前提供的/GS、DEP和ASLR漏洞利用阻斷技術。

1)在Visual Studio 2013中新建一個Win32控制臺應用程序,體驗/GS保護機制的作用。

2)了解Windows系統中DEP功能的啟用情況。

3)啟用ASLR服務。

【案例3思考與分析】

1./GS保護機制體驗

在Visual Studio 2013中新建一個Win32控制臺應用程序,附加選項中將“安全開發生命周期(SDL)檢查”取消設置。

運行結果如圖3-34所示。由于默認開啟了/GS編譯選項,系統可以有效地檢測到溢出并拋出異常,從而防止緩沖區溢出。

圖3-34 【例3-7】運行結果

分別查看使用/GS選項和未使用/GS選項編譯的VulnerableFunc函數反匯編代碼,如表3-2所示。

表3-2 使用/GS選項和未使用/GS選項編譯的反匯編代碼比較

觀察表3-2中使用/GS選項編譯的VulnerableFunc函數反匯編代碼可以發現,在函數調用發生時,向棧幀內壓入一個額外的隨機DWORD值,也就是安全Cookie,該值位于EBP之前,系統還將在內存區域中存放該值的一個副本。

在函數返回之前,系統執行一個額外的安全驗證操作,稱為Security Check Cookie。在檢查過程中,系統比較棧中存放的安全Cookie和原先副本的值。本程序中由于name數組中的字符個數多于output字符數組的長度,產生了溢出,破壞了安全Cookie值,導致與原先副本值不吻合,說明棧核中的安全Cookie已被破壞,即棧中發生了溢出。編譯器給出出錯提示。

出于性能優化的考慮,Visual Studio會評估程序中哪些函數需要保護,通常只有當一個函數中包含字符串緩沖區或使用_alloc函數在棧上分配空間時,編譯器才在棧中設置安全Cookie。此外,當緩沖區少于5個字節時,在棧中也不保存安全Cookie。

2.查詢Windows系統中的DEP是否啟用

如圖3-35所示,在Windows 8.1系統中,打開“控制面板”,依次選擇“系統和安全”→“系統”→“高級系統設置”→“高級”→“性能”頁框中的“設置”,就能看到“數據執行保護”選項卡。

3.開啟編譯器選項/DYNAMICBASE

在Windows系統中,Windows Server 2008及以后版本默認情況下啟用ASLR,但它僅適用于動態鏈接庫和可執行文件。Windows Server 2008及以上版本都啟用ASLR服務,但可以在項目屬性中修改/dynamicbase屬性,使其取消ASLR保護。

本例在Visual Studio 2013中通過開啟和關閉/DYNAMICBASE選項作示例。首先關閉/DYNAMICBASE選項,如圖3-36所示。

圖3-35 Windows系統中DEP功能設置

圖3-36 關閉/DYNAMICBASE選項

在Visual Studio 2013中新建一個Win32控制臺應用程序,附加選項中取消選擇“安全開發生命周期(SDL)檢查”復選框。輸入下列代碼。

這段程序的目的是輸出kerner32.dll基址、loadlibrary函數的入口地址,以及應用程序本身一個函數printAddress()的入口地址。

在不開啟ASLR的情況下,選擇“調試”→“開始執行(不調試)”命令,可以查看程序初次運行結果,如圖3-37a所示,重啟系統后,運行結果如圖3-37b所示。

圖3-37 關閉ASLR情況下的運行結果對比

a)初次運行結果 b) 重啟系統后的運行結果

由圖3-37可以看出,即使程序本身沒有使用ASLR,Kernel32.dll加載地址也發生了變化,這是因為Kernel32.dll庫已經選擇了被ASLR保護,但是應用程序自身printAddress()函數的地址是固定的。

在開啟ASLR的情況下,初次運行結果如圖3-38a所示,重啟系統后,運行結果如圖3-38b所示。

圖3-38 開啟ASLR情況下運行結果對比

a)初次運行結果 b) 重啟系統后的運行結果

由圖3-38可以看出,應用程序自身函數printAddress()的加載地址隨著系統重啟發生了變化,即一旦使用了/DYNAMICBASE選項,生成的程序在運行時就會受到ASLR機制的保護。

拓展閱讀

讀者要想了解更多Windows內存攻擊與保護的方法,可以閱讀以下書籍資料。

[1]王清.0 day安全:軟件漏洞分析技術[M].2版.北京:電子工業出版社,2011.

[2]DanielRegalado.灰帽黑客:正義黑客的道德規范、滲透測試、攻擊方法和漏洞分析技術[M].4版.李楓,譯.北京:清華大學出版社,2016.

主站蜘蛛池模板: 瑞安市| 左贡县| 沿河| 介休市| 潼关县| 青龙| 荔浦县| 昭苏县| 云龙县| 洪雅县| 瑞安市| 时尚| 阳朔县| 西华县| 射阳县| 杭锦旗| 防城港市| 改则县| 纳雍县| 定边县| 章丘市| 镇雄县| 渑池县| 修文县| 扶绥县| 沁源县| 五莲县| 聊城市| 日照市| 宿州市| 庆城县| 略阳县| 桃源县| 民权县| 敦化市| 铜川市| 长武县| 左权县| 黑水县| 屏东市| 崇左市|