對錯誤,漏洞和exploits的說明

 更新時間:2007年06月22日 00:00:00   作者:  
作者:Mark Vogels 
翻譯:黯魂[S.S.T] 

在這篇文檔中,我將會試著為你提供一個對于錯誤,和由于那些錯誤而產生的漏洞以及它們的exploits的基本認識。那決不意味著能讓你完全理解exploits和漏洞,但是能幫助你學會認識可能的漏洞以及怎樣處理它們。 

一般而言有3種不同類型的錯誤會可能危及計算機系統和網絡的安全。 
#編程錯誤 
#配置錯誤 
#設計錯誤 

錯誤可以被看成是失誤,盡管它們并非都是由事故導致的。軟件/設備的最初創建者可能就存在錯誤,用最好的想法卻創建了錯誤,并且沒有意識到它可能就是一個潛在的威脅。這聽上去可能有點糊涂,但是稍后在文章中都將會被澄清。為了深入探討關于錯誤的細節,我們需要創建一個對不同類型的錯誤的定義以至于我們能更容易認識它們。 

不同錯誤類型的定義 

編程錯誤: 

編程錯誤通常是由程序編寫者造成的。最常見的可利用編程錯誤是緩沖區溢出。把緩沖區溢出想象成一個空的杯子:程序的使用者將要倒咖啡到杯子里,但是程序編寫者事先并不知道使用者將會倒多少咖啡在里面。所以程序編寫者必須在使用者把咖啡倒進杯子之前檢查和測試,以阻止咖啡從杯子里溢出。有時候檢查輸入大小并不容易,或者由于時間緊迫,程序員沒有時間寫足夠廣泛的錯誤檢測函數。那么結果就是:可能的緩沖區溢出和其他的編程錯誤被創建。 

另一個編程錯誤的例子是:當用戶做一些預料之外的事,比如加載一個錯誤類型的文件到程序中時,程序會崩潰。當然不是所有的編程錯誤都需要用戶輸入才能做一些預料之外的事,像使程序崩潰。一個程序也會取決于總是在一個明確位置的特殊文件。如果那個文件被移動,并且程序員沒有預料到,他就不可能在程序嘗試打開它之前檢測文件是否還是在那個位置。假如程序在打開那個文件后嘗試用它運行,這就會導致不可預見的行為。 

這些類型的錯誤發生得相當頻繁,并且大多時候廠商都會分發補丁包來解決由消費者或者他們自己發現的被報告的錯誤。 

配置錯誤: 

這樣想象一個配置錯誤:如果你是一個網絡管理員并且你需要運行一個防火墻來保護你的網絡。習慣上,你會允許任何進出的流量,除專門拒絕的流量種類之外。 

一個簡單的例子是防火墻僅僅阻塞了80端口,然而它將允許來自因特網的任何人連接到防火墻的配置頁面重新配置它。其余的端口都是開著的。這明顯就是一個配置錯誤,任何人都能通過使用另一個端口號來繞過防火墻。 

幸運的是大多數廠商都知道這個錯誤,因此他們都正確的做了相反的處理:任何流量都被阻塞除非專門允許的。所以自從端口被關閉以后,網絡管理員都不再需要擔心發現的新問題,通過一個不使用的端口能訪問他的網絡。(這里我只使用端口來舉例子,不過這在相同的端口上也能應用不同類型的流量。) 

另一個配置錯誤的例子是,在一個網絡中的不受管理的hub代替可管理的交換機的用法。不同之處是,hub發送所有進入的數據包到所有的端口,因為它并不知道在它后面的接收者被定位到哪個端口,而交換機知道。所以,在一個使用hub代替交換機的網絡中運行一個sniffer,允許一個攻擊者查看包含可能的用戶名及密碼的更多數據包,解決辦法就是在網絡中使用交換機。即使現在這是一個配置錯誤,但在過去卻不是,因為那時交換機還不存在。 
  
設計錯誤: 

設計錯誤可以被看成是在軟件設計階段發生的錯誤。即使程序員花足夠的時間在軟件發布之前編寫檢測流程來檢驗所有用戶的輸入,即使軟件被最終用戶正確地配置,這些錯誤仍然會造成對于一個網絡的安全的極大危險。 

讓我們看看這種情況:一個公司決定開發一個軟件,這個軟件允許遠程訪問到一個網絡。那么他們也不得不支持這個軟件,從而他們決定放一些后門在里面以至于能使用公司名字作為密碼遠程登錄。如果公司以外的人發現了那些后門呢,會發生什么?他使用那個軟件的遠程訪問能夠登錄進任何一個網絡。結果將會是損失慘重的! 

盡管這些后門在過去被創建的相當頻繁,現在一個公司銷售類似的軟件卻不會再帶來風險了,因為他要對攻擊者的濫用后門負責。 

另一個設計錯誤的例子是使用在安全無線網絡中的WEP加密。我不打算深入說明這為什么是一個設計錯誤,畢竟那超出了這篇文章的范圍,但是它的基本流程是這樣的: 
一個3字節的初始化矢量增加到公鑰中來加密每個唯一的數據包。假設公鑰是abcde。第一個數據包的初始化矢量是123,因此這個數據包的全部密鑰就是123abcde。下一個數據包的初始化矢量是234,那么它的密鑰就是234abcde。 

設計錯誤在這里其實也就是,只有3字節的不同初始化矢量,導致了255^3或者說1650萬不同的keys以及部分加密算法被使用。通過逆向分析部分算法,能夠相當容易地獲得公鑰中的幾個字符。由于這個設計錯誤,你只需要用唯一的初始化矢量重復發送10萬個包(64-bit),發送80萬個包(128-bit),就能破解出WEP-key,便可以進入完整的無線網絡中。在一個繁忙的無線網絡中這能在幾小時內做到。 

那么你看到了,設計錯誤有點更難解決。你不能只是期望廠商發布快速更新來解決這個問題,你也不可能通過查閱產品說明書自己解決。針對WEP加密這種情況,一個小組創建了一個新的標準,叫做WPA。這意味著使用WEP加密的產品應該被取代,或者通過硬件更新以允許它們用這個新加密標準工作。對于已發現的WEP上的設計錯誤的細節描述,可以去看看airscanner。com上面的精華文章。 


這些錯誤如何成為漏洞的? 

一個漏洞就是對目標的保護方面的一個弱點。目標可以是連到一個完整網絡的一臺計算機的任何部分。我不會說明這兒可能的漏洞的所有不同,因為那幾乎不可能,但是我將設法指出什么是漏洞,以及漏洞如何產生的。 

按照早期的規定,最普遍的會成為漏洞的編程錯誤是緩沖區溢出。假設一個基于棧的緩沖區溢出,緩沖區被放置在棧中。??梢员豢闯墒悄愕奶幚砥鞔鎯祿诶锩娌⒛芘c其共同工作的一個臨時工作區?,F在,當你溢出一個放置在棧里的緩沖區時,你能夠寫數據到已分配空間的緩沖區之外,因此可以寫其它數據到棧中。而其它數據可以是調用函數的返回地址。假設調用函數的返回地址是12345678,并且返回地址直接存儲在緩沖區后面的棧中,那么??瓷先タ赡軙襁@樣: 
XXXXXXXXXX12345678 

XXXXXXXXXX是將包含我們的輸入的緩沖區。如果我們放一些比緩沖區大小要少的數據在里面,沒有任何奇怪的事會發生,但是當我們放12個'A'在這只能承載10個字符的緩沖區中時,多余的2個A就會覆蓋掉返回地址部分。從而使返回地址變成一個無效地址,然后函數無法返回,程序就崩潰了。 

如果這個程序是一個服務端應用程序,有人能放12個A使程序崩潰,并且導致其他所有用戶都無法訪問。這就成為了一個拒絕服務攻擊的例子。既然這樣,這個錯誤就有了拒絕服務漏洞。 

如果我們用與上面同樣的例子,但換一個更大的緩沖區,那么溢出緩沖區也就意味著更多的數據在一個實際溢出發生之前必須被放進去,可是當那發生時,我們可以寫一些計算機代碼(匯編指令),將其作為數據的一部分而放在緩沖區中使用。我們通過覆蓋它來改變返回地址,以指向我們溢出的緩沖區后面,程序將會試圖執行我們的緩沖區。這時,緩沖區包含了我們放進去的代碼,程序并不會崩潰,而是轉去執行我們的代碼。由于那些代碼可以是開啟一個shell(命令解釋程序)的一小段代碼,并且會在那臺計算機上監聽一個特殊端口,因此這種類型的代碼經常被稱作shellcode。 

隨著這些代碼的運行,有人便能夠連接到那個特殊的端口上,并能執行遠程命令,同時獲得與在遠程計算機開啟這個存在漏洞的應用程序的用戶所擁有的相同訪問權的控制權。 

對于配置錯誤,如果我們看看防火墻的例子,漏洞就更加明顯。假如那個防火墻能經由telnet遠程配置,那么僅僅不允許訪問防火墻的80端口會給網絡管理員一個安全上的錯誤認識,攻擊者仍舊能夠通過連接到防火墻的23端口進行訪問而配置它。 

然而,自從消費者開始要求他們所購買的產品應具有不同配置選項以后,廠商就開始著手研發高級別的可配置的軟件和設備。這可能讓一個設備的配置變得專業化而導致錯誤很容易發生。類似的設備的配置是如此的復雜,而漏洞能被網絡管理員看到,因此允許一個潛在的攻擊者訪問到網絡或系統中他本不應該訪問到的部分,所以一個簡單的配置錯誤會導致網絡和系統中存在一個潛在的漏洞。 

我已經給出了一個由設計錯誤導致漏洞的例子:WEP密鑰,但它很容易引出另一個設計錯誤的例子:設想一個軟件公司編寫了一個軟件用于瀏覽和創建文本文檔。他們想要出售他們的產品,然而由于競爭者的軟件公司也開發了一款相同功能的軟件,他們不得不設計一個表面上有更強大的功能的程序。因此他們決定增加一個特性以允許用戶能對自己創建的文檔有更多的控制,那樣用戶可以編寫小型函數(宏),并能被植入文檔中,同時能夠幫助文檔瀏覽者在他的計算機上做各種各樣的事情。如果所有這些功能被一個惡意攻擊者使用,創建一個已植入宏的文檔,能復制自身到機器上被找到的其他所有文檔中去,并且不經過瀏覽者的同意做各種各樣的其他事情呢?那么在這個被設計而創建的程序中,我們又有了一個可能的漏洞。 

你可以看到,一個錯誤會導致產生一個漏洞。在宏被使用在文檔中的情況下,幫助軟件用戶創建更多動態文檔的想法很偉大,除設計時沒有考慮安全因素以外。 


那么什么是一個exploit? 

exploit就是一種利用一個已發現的漏洞來改變程序或者系統初始功能的方法。這種方法對于一個攻擊者而言更有用處。在計算機安全中,術語"exploit"經常被用于描述一個特殊的程序,它的唯一目的就是自動利用一個漏洞來取得對有漏洞的目標程序的控制權,或者終止目標程序的正常功能。 

但是在一個系統或者網絡中使用一個錯誤的配置對要利用它的攻擊者來說,也能被叫做一個exploit,盡管它不一定非要是一個實際上能完成工作的特殊程序。 

我將通過一些C代碼的例子來試著說明一個exploit的作用,其中之一是一個存在緩沖區溢出漏洞的簡單的程序,另一個則是exploit。 

注意:這里給出的例子可能在不同的編譯器和系統上表現不同。你可能需要改變緩沖區中字符的數目才能真正改寫返回地址,或者exploitfunction的地址會不同,但是他們仍能工作。 

vulnerable_program.c: 


Copy code
#include "stdio。h" 
/*利用函數*/ 
exploitfunction() 

/*如果緩沖區溢出被成功利用,就會輸出此行內容*/ 
printf("This line will be printed after successfully exploiting the buffer overflow. "); 
system("pause"); 
ExitProcess(0); 


normalfunction(char *myargument) 

char buffer[10]; 
strcpy(buffer,myargument); 


main(int argc, char *argv[]) 

if(argc>1) 

normalfunction(argv[1]); 
printf(" These lines get printed during normal execution with at least 1 commandline argument.The address of exploitfunction 
is 0x%。8X ",&exploitfunction); 

else 
printf("Please provide the program with at least 1 commandline argument. "); 
ExitProcess(0); 


我已經創建了3個函數,一個是主函數,其他2個分別是:在正常情況下執行的normalfunction,以及利用函數exploitfunction。程序的目的是溢出緩沖區以至于返回地址將指向替換了normalfunction后面下一條指令的exploitfunction函數。 

現在我們需要指出文本字符串要多大才能完全覆蓋棧中的返回地址。有這個作為目標,就好辦了!我們每次增加一個字符直到程序崩潰。 

當我在Windows系統上使用Dev-cpp編譯完程序以后,我知道了在程序崩潰之前最多需要27個A。 
exploitfunction函數的地址以16進制形式表示,并且字節值經常表現出:地址是不可打印的字符。我寫了一個小程序,它將給這個易受攻擊的程序提供必要的字符串以利用它。 

在我的環境中,exploitfunction函數的地址(從易受攻擊的程序內部我方便地打印得到)是0x00401290。因為棧在Intel x86系統上是以逆序存儲所有數據的(這篇文檔中那不會被說明),我們需要準備一個相同的字符串。因此可能的值類似于
0x41414141414141414141414141414141414141414141414141414141901240. 

你可以看到,這里的字符'A'(0x41)我使用的是16進制的表現形式,那是存儲在棧中的真實值。結果就是,exploit非常簡單: 

Exploit.c: 


Copy code
#include "stdio.h" 
main() 

char workbuffer[200]; 
char tempbuf[4]; 
strcpy(workbuffer,"vulnerable_program AAAAAAAAAAAAAAAAAAAAAAAAAAAA"); 
tempbuf[0]=0x90; 
tempbuf[1]=0x12; 
tempbuf[2]=0x40; 
tempbuf[3]=0; 
strcat (workbuffer,tempbuf); 
system(workbuffer); 
return 0; 


這段程序所做的就是復制字符串"vulnerable_program AAAAAAAAAAAAAAAAAAAAAAAAAAAA"到一個緩沖區中,并用新的返回地址創建另一個緩沖區,附加在工作緩沖區之上。 
在那之后,程序調用system()來執行字符串中的命令。輸出結果是: 
C:>exploit.exe 
This line will be printed after successfully exploiting the buffer overflow. 
Press any key to continue…… 

太棒了,它執行了! 

難道那不偉大嗎? 

雖然我們實際上并沒有成功讓程序運行我們自己的代碼,但經過一些小小的改變就能完成。 
關于緩沖區溢出的更多相關信息請參考Aleph One寫的著名文章"Smashing the stack for fun and profit"

經過這篇文章的探討,你通常不得不自己行動來阻止你的系統或者網絡被一個已知漏洞所利用。對于配置錯誤我建議你請一位專家來幫你做必要的配置,因此在使用它之前你不用完全理解產品是如何運作的。對于編程和設計錯誤,通常有很多人進行產品測試,而其他人則發表他們發現的漏洞到Internet上的一些安全列表上。所以如果你保持持續關注這些安全列表,并確認你一直都在更新你的系統到最新版本,你就已經接近一個安全環境了。 

―――――――――――――――――――――――――――――――――――――――――― 
最近的安全編程文檔: 

《Exploiting Software How to Break Code》 
描述如何編寫exploit代碼的 

《Learning XML, 2nd Edition》 

《Writing Secure Code》 
微軟公司核心推薦,教你怎樣編寫安全的代碼 

《OReilly Web Site Cookbook》 
建立和管理你的網站的使用手冊,包括大量實例及解決方案

相關文章

最新評論

免费人成视频在线观看