漏洞型別及檢測

極安御信發表於2022-01-07


圖片


作者 | 榴蓮

編輯 | 楌橪


圖片

I.通用漏洞型別

 

1.棧溢位

 

棧溢位是緩衝區溢位的一種,往往由於對緩衝區的長度沒有判斷,導致緩衝區的大小超過了預定的大小,導致在棧內的儲存的返回地址被覆蓋,這時候返回地址將指向未知的位置.造成訪問異常的錯誤.

 

而當我們精心構造一段shellcode儲存在某個位置,並且透過滑板指令以及其他特定的方法跳轉至shellcode的位置上執行shellcode,此時就可以透過shellcode獲取到系統的管理員許可權.執行任意程式碼,

 

windows XP之前的系統可以直接利用,在windows7以後的系統需要構造ROP鏈突破保護許可權,突破方法見附錄1.

 

 

2.堆溢位

 

堆溢位與棧溢位一樣,也是緩衝區溢位的一種,堆疊溢位的產生往往是由於過多的函式呼叫,導致呼叫堆疊無法容納這些呼叫的返回地址,一般在遞迴中產生。堆疊溢位很可能由無限遞迴產生,但也可能僅僅是過多的堆疊層級

 

在 windows XP SP2上可以利用調整連結串列指標的方式,向固定的地址寫入可控的資料,比如講shellcode的地址寫到返回地址,或者覆蓋PEB函式指標.SEH結構等方法,但是隨著後續系統的更新,在windows 7系統中多了許多保護機制,因此需要構造ROP在繞過相關的保護機制後再利用漏洞獲取管理員許可權,執行任意程式碼.

 

 

3.整數溢位

 

整數分為有符號和無符號兩種型別,有符號數以最高位作為其符號位,即正整數最高位為1,負整數最高位為0,而無符號數沒有這種情況,它的取值範圍是非負數,在平時程式設計的時候常用的整型變數有 8位(單位元組字元、布林型別)、16位(短整型)、32位(長整型)等 ,每種整數型別在記憶體中有不同的固定取值範圍,比如unsigned short的儲存範圍是0-65535,但是當儲存的值超過65535的時候,資料就會截斷,例如輸入65536,系統就會識別為0.

 

如果利用整數溢位後的值做為記憶體複製的引數,那麼就會造成緩衝區溢位(堆/棧),利用方法就是緩衝區溢位的利用方法.

 

 

4.格式化字串

 

格式化字串漏洞的產生主要源於對使用者輸入內容未進行過濾,這些輸入資料都是作為引數傳遞給某些執行格式化操作的函式,如printf.fprintf.bprintf.sprintf等等.惡意使用者可以使用”%s”和”%x”等格式符,從堆疊或其他位置輸出資料,也可以使用格式符”%n”向任意位置寫入任意資料,配合printf()函式和其他功能類似的函式就可以向任意地址寫入被格式化的位元組數,可能導致任意程式碼執行,或者讀取敏感資訊,比如使用者名稱以及密碼等等.

 

因為可以執行任意程式碼,所以可以透過shellcode獲取系統管理員的許可權,也有可能透過一些技術,直接在記憶體中將系統密碼直接讀出.


 

5.雙重釋放

 

雙重釋放漏洞主要是由對同一塊記憶體進行二次重複釋放導致的,利用漏洞可以執行任意程式碼.

 

在釋放過程中,臨近的已釋放堆塊的合併動作,這回改變原有的堆頭資訊以及前後向指標,之後在對其中的地址進行引用,就會導致訪問異常,最後程式崩潰,正式因為程式引用到了已釋放的記憶體,所以說雙重釋放漏洞就是Use After Free漏洞的子集.如果程式不存在堆塊合併動作,那麼雙重釋放後可能不會馬上崩潰,但會在程式中遺留隱患,導致在後續執行過程中的某一刻爆發.

 

對於堆記憶體的利用,最常用也最簡單的方法就是使用堆噴射技術(Heap Spraying),也就是申請大量記憶體塊,將shellcode放在記憶體塊的最後,前面放上利用地址以及滑板指令,用大量記憶體來碰撞,直到最後執行到shellcode.

 

Shellcode可以執行任意程式碼,也就可以利用此來進行提權操作.

 

 

6.釋放重引用

 

UAF漏洞的成因一般都是因為在程式設計過程中對引用計數的處理不當導致物件被釋放後重用的。利用UAF漏洞實現遠端程式碼執行,首先需要Bypass ASLR,獲得模組基址及 shellcode的地址(也可以透過堆噴射在指定記憶體空間佈置shellcode),然後硬編碼、動態構造ROP來Bypass DEP,最終實現任意程式碼的執行。

 

 

7.陣列訪問越界

 

陣列訪問越界類似於溢位漏洞,但是又不完全是溢位漏洞

 

A)陣列訪問越界包含讀寫型別,而溢位屬於資料寫入

 

通常陣列越界訪問是由於陣列下標數值超出了陣列元素個數導致的,陣列的讀寫操作有時是同時並存的,程式越界索引棧上分配的陣列,同時又向其寫入資料.最終造成溢位.

 

B)部分溢位漏洞的本質就是陣列越界

 

導致溢位的原因有多種,有些正是由於針對陣列下表標範圍未做有效限制,導致允許越界訪問陣列並對其寫入資料,造成溢位

 

 

8.核心級漏洞

 

在Ring3的溢位漏洞,格式化字串漏洞,釋放重引用漏洞,雙重釋放漏洞,陣列越界漏洞都可以在核心中復現,但是利用方法差異比較大.

 

核心漏洞不易挖掘,也不易分析利用.但是如果可以利用成功,那麼直接可以使用Ring0許可權.


 

9.型別混淆

 

型別混淆漏洞主要是講資料型別A當做資料型別B解析引用,可能導致非法訪問資料,進而執行任意程式碼,但這裡的資料型別並非是單純的程式設計概念上的資料型別,比如Uint被轉換成String,Flash漏洞:CVE-2014-0590,也包括類物件或者資料結構的轉換,比如以下兩個類,A類被混淆成B類,就可能導致私有域被外部訪問到.

 

 

10.沙盒逃逸

 

A)Broker介面漏洞:IE藉助Broker程式完成一些需要高許可權的操作,若其服務埠本身就存在漏洞,就可以直接被攻擊者用於執行任意程式碼.

 

B)策略檢查繞過:Broker程式在檢查Elevation Policies時若被繞過也可能導致沙盒逃逸,比如CVE-2013-4015用Tab帶起空格從而繞過對程式名的檢查.

 

C)策略設定不當:對於沙箱可操作的程式,如果其Elevation Policies設定不當,允許靜默以Medium許可權執行,就可能建立高許可權的程式再借助該程式的一些介面完成任意程式碼執行.

 

D)IPC通訊問題:當IPC通訊過程中使用的共享記憶體包含過多的IE的未註冊資訊,可能導致沙盒的程式篡改其中主程式中的敏感資訊,比如EPM沙盒的開關標準,被篡改後就可以直接關閉沙盒

 

E)沙盒許可權限制不嚴:在沙盒中的程式如果許可權限制的不夠嚴謹,使得本不改訪問的安全物件被訪問,就可能導致沙盒逃逸.

 

F)核心提取:利用系統核心漏洞獲取比沙盒本更更高的許可權,就可以直接關閉沙盒本身,從而實現沙盒逃逸.

 

 

11.RPC漏洞

 

RPC是一種遠端過程呼叫協議,RPC提供程式間的互動通訊機制,允許在某臺計算機上執行的程式無縫的在遠端系統上執行.

 

因為TCP/IP處理交換等問題,導致惡意程式碼可以利用漏洞以本地系統許可權在系統上執行任意指令.


 

V.檢測方法

 

1.shellcode模糊檢測

A)利用特定的編碼方式檢測

1)/x**:類C語言的shellcode編碼形式

2)/u****:類javascript的shellcode編碼形式

 

3)%u****:類JavaScript的shellcode編碼形式

4)%**:多種指令碼使用的shellcode編碼形式

 

 

B)利用GetPC的特徵來匹配shellcode

1)E80000000058方式GetPC

2)E8FFFFFFFFC258方式GetPC

3)D9EED97424F45B方式GetPC


 

C)利用動態函式獲取編碼來匹配shellcode

1)利用shellcode必須動態獲取函式地址,以擺脫對宿主的環境要求的特點,針對動態獲取函式地址的編碼來進行檢測

 

 

D)利用滑板指令來匹配shellcode

1)可以利用大量出現的滑板指令來匹配shellcode,例如0C0C0C0C,90909090,FFFFFFFF等經典滑板指令

 


2.惡意行為模糊檢測

A)針對不應該出現的敏感庫進行檢測,如文件中如果出現ws2_32.dll就屬於不正常的情況,可以針對性檢測

B)針對不應該出現的敏感函式進行檢測,如文件中如果出現申請記憶體,download等敏感操作,可以針對性程式檢測

C)針對敏感物件以及欄位進行檢測,如果出現updata,autoopen一類敏感物件或欄位,可以針對性進行檢測

D)針對未知網址的檢測,如果文件中出現非官方網址的未知網址,那麼可以針對其進行針對性檢測

 

 

3.漏洞特徵檢測

A)利用逆向分析出的漏洞觸發特徵,進行漏洞精確檢測

 

附錄1(windows保護機制):

GS:

在所有函式呼叫發生時,向棧楨裡面壓入一個隨機的DWORD,這個數被稱為canary,canary位於EBP之前,系統還在資料段的記憶體區域中儲存一個canary的副本,當棧中發生溢位的時候,canary將被首先淹沒,之後才是EBP和返回地址

在函式返回之前,系統做一個額外的安全驗證,確認棧楨中的canary與資料段中的副本是否一致,如果兩者不一致,說明棧楨中的canary已經被破壞,也就是棧中發生了溢位。

 

 

突破GS:

1.利用不受保護的記憶體突破,例如某函式中不包括4位元組以上的緩衝區,即使開啟GS,也並沒有保護

2.利用虛擬函式突破,將虛表指標指向我們說需要的位置

3.利用異常處理突破,GS機制並沒對SEHJ進行保護,我們可以透過超長字串覆蓋掉異常處理函式指標,然後觸發一個異常,這時候就會轉入異常處理,但是異常處理函式指標被覆蓋了,那麼就可以劫持SEH來控制程式流程了

4.利用GS自身驗證突破,同時替換棧中和資料段中的canary

 

SafeSEH:

編譯器:

在編譯的時候產生一張安全SEH表,並且將這張表放在程式的映像裡,當程式呼叫異常處理函式的時候,首先檢查呼叫的異常處理函式是否在安全SEH表裡。

作業系統:

1.檢查異常處理鏈是否處於當前棧中,如果不在,程式終止異常處理的呼叫

2.檢查異常處理函式指標是否指向當前程式的棧中,如果指向,終止異常處理函式的呼叫

3.呼叫RtllsValidhandler()來進行有效驗證

     1)檢查程式上是否設定了IMAGE_DLLCHARACTERISTICS_NO_SEH標記。如果設定了這個標識,這個程式內的異常將會被胡烈,所以這個標誌被設定時,函式直接返回效驗失敗

     2)檢測程式是否包含安全SEH表,如果程式中包含安全SEH表,則將當前的異常處理函式地址和該表進行匹配,匹配成功則返回校驗成功。匹配失敗則返回校驗失敗。

     3)判斷程式是否設定ILonly標識,如果設定了這個標識,說明該程式 只包含.NET編譯人中間語言,哈數直接返回校驗失敗

     4)判斷異常處理函式是否位於不可執行頁上,當異常處理函式地址位於不可執行頁上,校驗函式會檢測DEP是否開啟,如果系統未開啟DEP則返回校驗成功,否則程式丟擲訪問異常。

突破SafeSEH:

1.攻擊返回地址,如果啟用了safeSEH而沒有啟用GS,或者剛好這個函式沒有GS保護,那麼就可以直接攻擊函式返回地址

 

2.利用虛擬函式表來劫持程式流程,這個過程中不涉及任何異常處理。SafeSEH也就沒有機會生效了

3.利用未啟用SafeSEH的模組繞過SafeSEH

 

DEP:

DEP的基本原理就是將資料所在的記憶體頁標識為不可執行,當程式溢位後執行shellcode的時候,就會嘗試在資料面上執行指令,此時CPU就會丟擲異常,而不是去執行惡意的指令

根據機制的不同可以分為軟體DEP和硬體DEP

軟體DEP就是SafeSEH

硬體DEP才是真正意義上的DEP,需要CPU的支援,透過設定記憶體也的NX屬性標記,來表明不能從該記憶體執行程式碼。當NX標記為0的時候表示這個頁面可以執行指令,當NX標記為1的時候表示不能執行指令

 

突破DEP:

1.利用ret2libc

     1)透過跳轉到ZwSetInfromationProcess函式將DEP關閉再轉 Shellcode執行。

     2)透過跳轉到Virtualprotect函式來將shellcode所在的記憶體也設定為可執行狀態,然後轉入shellcode執行

     3)透過跳轉到VirualAlloc函式開闢一段具有執行許可權的記憶體空間,然後將shellcode複製到這段記憶體中執行

2.利用可執行記憶體

     如果程式空間裡存在一段可讀可寫可執行的記憶體,那麼如果我們可以將shellcode複製到這段記憶體中,並且劫持程式執行流程,那麼我們的shellcode就有執行的機會

3.利用java applet

     它可以被載入到IE客戶端中,而且載入到IE程式的記憶體空間後,這些空間與空間都具有可執行屬性

 

ASLR:

1.基址隨機化

 

2.堆疊隨機化

3.PRB和TEB的隨機化

突破ASLR:

1.利用沒有開啟ASLR的模組進行繞過,比如Flash外掛

2.利用部分覆蓋進行定位,基址隨機化只隨機了前2個位元組,這樣就可以利用這個地址的後兩個字來在一定程度上控制這個程式。

3.利用堆噴射進行記憶體定位。

    1.Heap spary:堆噴射就是申請大量記憶體,佔領記憶體中的0x0c0c0c0c,並且在這些記憶體中放置0x90(nop)和shellcode,最後控制程式轉入0x0c0c0c0c執行,只要不是0x0c0c0c0c整好處於shellcode當中,那麼shellcode就可以成功執行。

     思路:申請200個1MB的記憶體塊來堆噴,每個記憶體塊中包含0x90和shellcode,堆噴結束後我們就會佔領0x0c0c0c0c附近的記憶體,只要控制程式轉到0x0c0c0c0c執行,透過0x90就滑板,最終執行shellcode

     在程式中找到溢位點,覆蓋其返回地址,將返回地址覆蓋為0x0c0c0c0c,這樣函式返回執行的時候就會跳到我們申請的記憶體中

 

SEHOP:

SEHOP的核心任務是檢查SEH鏈的完整性,在程式轉入異常處理前SEHOP會檢查SEH鏈上的最後一個異常處理函式是不是系統的異常處理函式,如果是,那麼說明異常處理鏈沒有被破壞,如果不是,那麼說明SEH鏈已經被破壞,可能發生了覆蓋攻擊,程式不會執行當前的異常處理程式。

突破SEHOP:

1.偽造SEH鏈結構

2.利用未開啟SEHOP的模組進行突破。圖片

直播預告:

直播主題:8日HOOK專題      9日lnject專題

直播時間:20:00-21:30     

直播平臺:B站/騰訊課堂/微信影片號


關於作者

作者:rkvir(榴蓮老師)

簡介:曾任某安全企業技術總監;看雪講師;曾任職國內多家大型安全公司;參與*2國家級安全專案

擅長:C/C++/Python/x86/x64彙編/系統原理&

研究方向:二進位制漏洞/FUZZ/Windows核心安全/內網攻防


相關文章