?

Windows棧緩沖區溢出攻擊原理及其防范

2017-10-28 21:43李云飛陳洪相
軟件工程 2017年9期
關鍵詞:堆棧安全漏洞內存

李云飛 陳洪相

摘 要:計算機網絡安全漏洞和網絡攻擊伴隨著網絡的存在會隨時發生,棧緩沖區溢出漏洞攻擊是網絡攻擊中最常見的一種攻擊技術。文章剖析了Windows棧工作原理,以及棧溢出漏洞攻擊技術方法,針對常見的棧溢出漏洞攻擊提出了幾種防御措施,能預防大部分針對棧溢出漏洞的攻擊。

關鍵詞:網絡安全;內存;安全漏洞;堆棧;緩沖區溢出

中圖分類號:TP309.1 文獻標識碼:A

Abstract:Computer network security vulnerabilities and cyber attacks may occur at any time on the Internet,and the stack buffer overflow attack is the most common network attack technology.This paper analyzes the operating principle of the stack in Windows and the techniques of stack overflow attacks.Then,several prevention measures are proposed for common stack buffer overflow attacks,which can prevent most stack overflow attacks.

Keywords:network security;memory;security vulnerabilities;stack,buffer overflow

1 引言(Introduction)

緩沖區是已分配的一段大小確定的用于臨時存放數據的內存存儲區。當向一個已經分配了確定內存空間的緩沖區內寫入超出該緩沖區處理能力的數據時,將發生緩沖區溢出[1]。

近十年,以緩沖區溢出為類型的安全漏洞攻擊是最為常見的一種形式,在網絡與分布式系統安全中,50%以上的漏洞攻擊都是基于緩沖區溢出技術的,尤其在不進行邊界檢查的C/C++程序中仍然是軟件可靠性和安全性的主要威脅之一[2]。

利用緩沖區溢出攻擊,可以導致程序運行失敗、重新啟動、執行惡意代碼等后果。緩沖區溢出中最危險的是棧溢出,因為入侵者可以利用堆棧溢出,在函數返回時改變返回程序的地址,讓其跳轉到任意地址,更為嚴重的是,它可被利用來執行非授權指令,甚至可以取得系統特權,進而進行各種非法操作[3]。

2 Windows棧緩沖區溢出原理(The principle of

stack buffer overflow in Windows)

2.1 Windows內存程序結構

計算機運行時,必須首先把程序從外存裝載到內存,然后由CPU從內存中依次讀取執行指令。正在運行的程序叫進程,每個進程都有自己的獨立內存空間,它被分成幾個段(Segment),分別是代碼段(text)、數據段(data,bss)、堆(heap)、棧(stack)等,如圖1所示。用戶進程的內存空間,也是系統內核分配給該進程的虛擬內存。內存總是被進程占用,但并不表示這個進程占用了這么多的物理內存,Windows將虛擬內存地址映射到各進程的物理內存地址上,進程內存空間隨著程序的執行會增大或者縮小[4]。

堆和棧都是一種數據項按序排列的數據結構。

棧是一種先進后出的數據結構,是自動開辟空間,用來分配局部變量、類的引用(指向堆空間段),棧使用的是一級緩存,通常在被調用時處于存儲空間中,調用完畢立即釋放。

堆是一種經過排序的數據結構,每個結點都有一個值,可以被看成是一棵樹,堆的存取是隨意的,堆是存放在二級緩存中,生命周期由虛擬機的垃圾回收算法來決定。堆的特點是根結點的值最?。ɑ蜃畲螅?,且根結點的兩個子樹也是一個堆。由于堆的這個特性,常用來實現優先隊列。

bss段(Block Started by Symbol segment)通常是指用來存放程序中未初始化的全局變量的一塊內存區域,屬于靜態內存分配,程序一開始就將其清零了。

對于一個進程的內存空間而言,可以在邏輯上分成三個部分:代碼區、靜態數據區和動態數據區。動態數據區一般就是堆棧。進程的每個線程都有私有的棧,所以每個線程雖然代碼一樣,但本地變量的數據都是互不干擾。全局變量和靜態變量分配在靜態數據區,本地變量分配在動態數據區,即堆棧中。程序通過堆棧的基地址和偏移量來訪問本地變量[5]。

32位系統中經典的內存布局是:程序起始1GB地址為內核空間,接下來是向下增長的??臻g和由0×40000000向上增長的內存映射地址。而堆地址是從底部開始,去除ELF(Executable and Linking Format)、代碼段、數據段、常量段之后的地址并向上增長,這種布局導致了緩沖區容易遭受溢出攻擊[6]。

2.2 Windows棧緩沖區溢出原理

Windows程序的執行流程由代碼段ECS和指令指針EIP控制,EIP始終指向下一條要執行指令的地址。當發生中斷或要調用子程序時,需要將當前斷點信息入棧保存,然后轉去執行中斷子程序,執行完中斷子程序后返回指令將棧頂內容出?;謴蛿帱cECS和EIP。

這種控制流程看似簡單,只需將指令地址按序給ECS和EIP即可,但就是因為這簡單的控制而不容許有任何地址計算差錯。如果其他緩沖區溢出會導致多余的數據覆蓋其他有用內存空間,其中如果將棧內數據覆蓋就可能導致修改入棧保存的ECS和EIP,從而使得程序返回時跑飛。

當一個函數被調用時,函數參數、EIP、ECS(段間調用時)、EBP和函數局部變量會依次壓棧保存,如圖2所示。endprint

定義變量和正常調用時如圖3(a)和圖3(b)所示,但當把遠大于10個字符的內容(如字符"B")拷貝到為緩沖區分配的10個字符空間時,多于10個字符的內容就會覆蓋掉EBP和ECS:EIP,如圖3(c),函數執行完畢后返回的地址就已經不是原來保存的正確地址了。

如果溢出部分的數據量足夠大或經過攻擊者的精心設計,就可能覆蓋返回地址,從而改變程序的執行流程,將程序的返回地址修改成其想執行的代碼地址,達到攻擊目的。

出現緩沖區溢出的情況主要包括三種:

(1)使用非類型安全的語言。緩沖區溢出主要出現在C和C++語言中,雖然C/C++語言可以允許程序員直接訪問內存和CPU的寄存器,從而創建非常接近硬件運行的性能優異、運行速度快程序,但C/C++語言不執行數組邊界檢測和類型安全檢查,所以在進行數組、字符串操作時容易造成緩沖區溢出[7]。

(2)以不安全的方式訪問或操作緩沖區。如果應用程序需要獲得數據,當用戶將數據復制到應用程序所指定的緩沖區而未考慮目標緩沖區的大小時,就可能造成緩沖區溢出。

(3)編譯器將緩沖區放在內存中關鍵數據結構旁邊或鄰近的位置。

3 Windows棧緩沖區溢出攻擊防范(The prevention

methods of stack buffer overflow attacks

Windows)

在棧溢出的檢查與防范方面,許多軟硬件廠商已經做了大量工作,如微軟在Visual Studio中增加編譯選項來檢測棧的溢出,在Windows系列操作系統中增加了SEHOP (Structured Exception Handling Overwrite Protection),阻止修改SEH增強系統的安全性,硬件方面,64位CPU引入了NX(No-eXecute)機制,在內存中區分數據區與代碼區,當攻擊者利用溢出使CPU跳轉到數據區去執行時,就會異常終止等[8]。

但對大量現有軟硬件資源,若要都升級或更新到最新的軟硬系統是一件很困難的事,而且不斷有繞過防御機制的新漏洞產生,攻擊方法也在不斷地發展變化。所以日常工作中的防御措施相當必要,針對不同的攻擊原理和方法,也可以靈活采用各種技術進行針對性的防御。

緩沖區溢出攻擊防范是和整個系統的安全性分不開的。除了系統管理上采用諸如關閉危險的特權程序,及時下載系統或軟件的最新補丁,使用安全產品等措施之外,軟件開發過程中的防范才是從根源上解決問題的渠道,常用的方法主要有幾種[9]。

3.1 GS編譯選項

Windows在Visual Studio 7.0(Visual Studio 2003)及以后版本中添加了一個針對函數的棧緩存溢出安全編譯選項——GS,來增加棧溢出的難度。

GS編譯選項的原理就是在堆棧上插入一個安全cookie,以測試堆棧上的返回地址是否被修改過。安全cookie為四個字節,在堆棧上的位置如圖4和圖2的傳統內存結構相比,GS編譯選項會增加四個字節的堆??臻g。

如果是堆棧的局部變量發生緩存溢出的錯誤而導致返回地址被覆蓋的話,由于安全cookie所在的位置,它也一定會被覆蓋。GS編譯選項在函數的入口和出口添加了針對安全cookie操作的指令,如果發現安全cookie的值被改動就會轉入異常處理終止程序運行。

如果堆棧上的安全cookie的值和security_cookie的值一致的話,那么函數正常退出,否則就會執行錯誤處理程序。

3.2 軟件開發過程防范

發生棧緩沖區溢出的主要原因是軟件程序中使用了不規范的數據操作或惡意代碼攻擊,所以在軟件的編寫過程中注意規范的代碼審查,是杜絕緩沖區溢出的最直接因素。

(1)規范代碼編寫規則

C和C++開發工具不是為安全而設計的,屬于非類型安全語言,為了保證編程的靈活性,C/C++的一些庫函數(如strcpy(、gets()等))缺乏邊界檢測,如果調用時輸入的參數過長,就會導致緩沖區溢出。所以在使用C/C++開發工具編程時,都應該有針對性地進行安全性測試和代碼審查。

①數組邊界檢測。C語言不進行數組邊界檢測,容易產生超長數據操作植入代碼,導致緩沖區溢出。當在編譯時檢查所有的數組讀寫操作,確保對數組的操作都在有效范圍內。

目前的C程序編譯調試檢測提供了許多檢測工具,主要對存儲器存取檢測、數組邊界檢查。譬如Purify使用目標插入代碼技術檢查可執行代碼在執行時數組的所有應用來保障數組的合法使用,但程序的性能不可避免地要受到影響。

但由于所有的C數組在傳送時是按指針傳送的,所以傳遞給調用函數的數組不會被檢查。例如庫函數strcpy()、strcat()、gets()等函數,在編譯時不會進行邊界檢查。

②指針完整性檢查。程序的指針完整性檢查在程序指針被引用之前檢查其是否被改變,即使攻擊者成功改變了程序指針,由于系統提前檢測到了該改變而不執行該指針,所以該方法在防范緩沖區溢出方面性能比較好。

程序指針完整性檢查是在函數返回地址或者其他的關鍵數據、指針之前插入防范值,或者存儲一個返回地址、關鍵數據或指針的備份,在函數返回時進行比較。

③改進C庫函數。C語言產生緩沖區溢出的根本是調用一些庫函數時不對數據進行邊界檢測,比如strcpy()gets()、strcat()、scanf()、printf()等,所以在用到該類型的庫函數時,可以開發更安全的替代函數實現該部分功能,并對其進行安全檢查調用,防范緩沖區溢出。

(2)棧的不可執行技術

Windows系統為了實現更好的性能和功能,往往在數據段中動態地插入可執行的代碼,這樣當緩沖區發生數據溢出時就會覆蓋數據段,從而可能導致數據段中的可執行代碼被修改。所以為了防止這種緩沖區溢出產生攻擊,可以使被攻擊程序的數據段地址空間不可執行,從而使得攻擊者不可能執行被植入攻擊程序的緩沖區代碼。endprint

為了保持程序的兼容性不可能將所有程序的數據段設為不可執行,但可以在必要的時候將堆棧數據段設為不可執行,因為幾乎沒有程序會在堆棧中存放代碼,所以這樣既可以最大限度地保證程序的兼容性,也可以有效地保證棧緩沖區溢出攻擊。

(3)備份關鍵控制信息

棧溢出攻擊程序最致命的攻擊就是將程序流程的EIP和ECS內容修改,導致原程序流程不能正常執行。如果在調用程序或入棧時,將斷點的EIP和ECS自動入棧的同時,用另外申請的靜態或動態數組將程序流的關鍵信息如EIP和ECS備份保存,當出棧返回程序斷點時,用備份的信息和棧中的信息進行比對,如果發現不一致則認為棧內容被修改,這時可以做出中斷檢測處理,防止進入攻擊代碼。

3.3 棧溢出檢測防范技術

(1)漏洞特征檢測

漏洞都有一定的觸發條件,其攻擊過程就是構造外部輸入使之滿足觸發條件,針對棧溢出漏洞的攻擊觸發條件就是要注入超過系統邏輯計劃存儲的數據長度。根據漏洞的攻擊特性系統會建立一個特征信息庫并動態更新,當程序執行過程中系統會針對該信息庫進行網絡流量檢測,當發現有類似特征代碼就會及時采取有效措施或阻止,避免發生棧溢出漏洞攻擊。

(2)攻擊特征檢測

漏洞需要被攻擊者發現并利用才能被安全機構通過特征進行檢測,這需要觸發條件或可能經過很長時間才能被發現。為了及時防御該類溢出攻擊,可以根據攻擊的特點進行有針對性的防御。

棧溢出注入數據的長度與內容隨著漏洞的不同而有所差異,但攻擊者攻擊時所使用的跳轉地址卻是常用或者比較固定易用的一些地址。由于不同平臺下的shellcode一般都會重復利用。所以棧溢出攻擊手法會具有一定的特征,通過提取這些頻繁出現的特征對防御設備的攻擊特征庫及時更新,可以有效阻止棧溢出攻擊發生。

(3)虛擬檢測技術

防御設備最理想的情況是可以虛擬出一個除了數據不同其他均相同的虛擬機,通過在虛擬系統中插入檢測點,檢測系統某一進程完成后的現場跟蹤進程的運行狀態。如果進程的操作沒有異常,后臺再把操作重定向到真實的進程去處理,把真實數據返回給用戶,否則可以阻止其對真實系統的訪問。

4 結論(Conclusion)

計算機網絡攻擊幾乎每時每刻都會發生,攻擊的方式變化多樣且會隨著防御技術的變化而不斷變化,所以對網絡攻擊的防御是個長期的持久戰。本文提出的攻擊原理和防御技術能有效地阻止大部分棧溢出攻擊,但攻擊技術在不斷地發展,我們還需要根據新的攻擊技術研究設計更有效的防御技術。

參考文獻(References)

[1] Nashimoto S,et al.Buffer overflow attack with multiple fault injection and a proven countermeasure[J].Journal of Cryptographic Engineering,2016,7(1):1-12.

[2] Sui Y,et al.Eliminating Redundant Bounds Checks in Dynamic Buffer Overflow Detection Using Weakest Preconditions[J].IEEE Transactions on Reliability,2016,65(4):1682-1699.

[3] Wang X,et al.A Differential Approach to Undefined Behavior Detection[J].Acm Transactions on Computer Systems,2015,

33(1):1.

[4] 肖蕾,劉克江.一種微型嵌入式系統動態內存分區管理機制的研究[J].軟件工程,2016,19(4):59-60.

[5] 崔寶江,等.基于污點信息的函數內存模糊測試技術研究[J].清華大學學報(自然科學版),2016(1):7-13.

[6] 彭建山,等.基于指針時空分析的軟件異??衫眯耘卸╗J].計算機應用研究,2016,33(5):1504-1508.

[7] 謝汶兵,等.基于備份控制流信息的緩沖區溢出監測技術[J].計算機工程與應用,2016,52(11):101-107.

[8] Jaiswal S,Gupta D.Security engineering methods-in-depth analysis[J].International Journal of Information & Computer Security,2017,9(3):180.

[9] Howard M,Lipner S.The security development lifecycle:SDL,a process for developing demonstrably more secure software[J].Datenschutz und Datensicherheit-DuD,2015,34(3):135-137.

作者簡介:

李云飛(1974-),男,博士,副教授.研究領域:信息安全,嵌入式系統,模式識別.

陳洪相(1974-),男,本科,高級教師.研究領域:計算機應用,軟件開發.endprint

猜你喜歡
堆棧安全漏洞內存
外部高速緩存與非易失內存結合的混合內存體系結構特性評測
“春夏秋冬”的內存
安全漏洞太大亞馬遜、沃爾瑪和Target緊急下架這種玩具
嵌入式軟件堆棧溢出的動態檢測方案設計*
基于堆棧自編碼降維的武器裝備體系效能預測
基于安全漏洞掃描的校園網告警系統的開發與設計
安全漏洞Shellshock簡介
基于內存的地理信息訪問技術
一種用于分析MCS-51目標碼堆棧深度的方法
NSFOCUS 2010年2月之十大安全漏洞
91香蕉高清国产线观看免费-97夜夜澡人人爽人人喊a-99久久久无码国产精品9-国产亚洲日韩欧美综合