如今,在病毒肆虐、黑客無處不在的網(wǎng)絡(luò)環(huán)境里,軟件的安全性已成為一個備受關(guān)注的話題。傳統(tǒng)的軟件安全性關(guān)注的主要在于權(quán)限與角色的管理,如訪問控制,或是數(shù)據(jù)的機(jī)密性與完整性,如加密解密。但是一個軟件系統(tǒng)在應(yīng)用了這些安全措施之后就能確保其萬無一失了嗎?答案似乎并不那么簡單,其中一個重要(甚至可以說致命)的問題在于軟件系統(tǒng)中的漏洞。常常在一個看似牢不可破的系統(tǒng)中,僅僅是因?yàn)榇嬖谝粋€小小的漏洞,導(dǎo)致整個安全體系被黑客輕易地攻破,整個系統(tǒng)的控制權(quán)徹底喪失。
所謂漏洞,通常是指軟件中存在的一些bug,但這種bug又不同于普通軟件測試中的bug.普通軟件測試中的bug指的是功能性或邏輯性的錯誤,如對話框彈出出錯、系統(tǒng)執(zhí)行某功能失敗等。這些bug影響的只是用戶的使用體驗(yàn),并不對系統(tǒng)的安全構(gòu)成威脅。而軟件的安全漏洞指的是某些別有用心的用戶非正常的使用軟件,讓軟件執(zhí)行一些自己精心設(shè)計的惡意代碼,或解析畸形文件,當(dāng)軟件中存在安全漏洞的時候,程序的正常執(zhí)行流程被改變,從而達(dá)到獲取系統(tǒng)的控制權(quán)或竊取機(jī)密數(shù)據(jù)的目的。
數(shù)據(jù)庫系統(tǒng)是在操作系統(tǒng)平臺之上的最重要的系統(tǒng)軟件,數(shù)據(jù)庫系統(tǒng)的安全可以說是十分重要的。曾經(jīng)有句話這樣說:如果網(wǎng)絡(luò)遍地是金錢,那么金錢就在數(shù)據(jù)庫服務(wù)器中。隨著無紙化業(yè)務(wù)環(huán)境的不斷擴(kuò)大,人們在數(shù)據(jù)庫中存儲著越來越多的敏感信息:銀行賬戶、醫(yī)療記錄、政府文件、軍事機(jī)密等等,數(shù)據(jù)庫系統(tǒng)就成為越來越有價值的攻擊目標(biāo),因此確保數(shù)據(jù)庫系統(tǒng)的安全也越來越重要。
作為一種大型的系統(tǒng)軟件,數(shù)據(jù)庫系統(tǒng)中也存在著各種各樣的安全漏洞,其中危害性較大的有緩沖區(qū)溢出、堆溢出和SQL注入等。
1.緩沖區(qū)溢出
緩沖區(qū)溢出是一種很常見也很古老的安全漏洞。早在上個世紀(jì)80年代,緩沖區(qū)溢出就已經(jīng)為人所知,但時至今日,大量的緩沖區(qū)溢出漏洞仍被發(fā)現(xiàn)。最著名的Morris蠕蟲就是利用Unix系統(tǒng)上fingerd程序的緩沖區(qū)溢出漏洞。在Oracle 9i發(fā)布之初,Oarcle公司曾宣稱他的數(shù)據(jù)庫是“ unbreakable ”的,但不到幾個月的時間,就暴出Oracle 9i中oracle.exe、XDB等程序存在多個緩沖區(qū)溢出漏洞。
在C語言中最常見的緩沖區(qū)就是字符數(shù)組,而操縱字符數(shù)組的函數(shù)有g(shù)ets、strcpy、sprintf等。這些函數(shù)在執(zhí)行字符串拷貝的過程中沒有對字符串進(jìn)行長度檢查,這樣就很容易發(fā)生超長的字符串溢出緩沖區(qū)的情況。當(dāng)初這樣設(shè)計是出于效率的考慮,但現(xiàn)在看來,這些函數(shù)的使用已成為C語言軟件脆弱的一個重要因素。如果程序員沒有良好的編程習(xí)慣,時刻注意函數(shù)調(diào)用過程中是否拷貝了超過緩沖區(qū)長度的字符串,那么緩沖區(qū)溢出就不可避免。對于一個有緩沖區(qū)溢出漏洞的程序,當(dāng)普通用戶輸入超長字符串時,通常只會使該程序崩潰。例如對于下面一小段代碼:
/* vulprog */ #include int main(int argc , char * argv[]) { char buff[8]; strcpy(buff, argv[1]); }
如果用戶執(zhí)行 ./vulprog AAAAAAAAAAAAAAAA,在Linux上會出現(xiàn)段錯誤,因?yàn)橛脩糨斎肓顺L的字符串,除了填滿了緩沖區(qū),還覆蓋了其他一些程序正常退出所需要的數(shù)據(jù)。為了研究這個問題,就需要了解Linux系統(tǒng)中進(jìn)程的內(nèi)存空間。
在Linux系統(tǒng)中,2G~3G的內(nèi)存地址是普通用戶進(jìn)程的加載空間,其內(nèi)存布局如下圖所示:
從圖中可以看出棧結(jié)構(gòu)是從高地址增長到低地址,而進(jìn)行函數(shù)調(diào)用時系統(tǒng)所作的“序幕”工作就是將函數(shù)的返回地址和EBP壓棧,再將ESP賦給EBP使其成為局部基指針,最后ESP減去一定的值為局部變量留出空間。
這樣當(dāng)程序?qū)⑦^長的字符串拷貝到緩沖區(qū)時就會依次覆蓋EBP和返回地址。當(dāng)用AAAA覆蓋返回地址,函數(shù)退棧時系統(tǒng)就將0x41414141(A的16進(jìn)制ASCII碼)賦給EIP去執(zhí)行,由于是一個非法的內(nèi)存地址,故程序崩潰。
但如果用一個實(shí)際存在的地址覆蓋返回地址,那么程序就轉(zhuǎn)而去執(zhí)行該地址處的指令,通常黑客會在這個地址植入所謂的shellcode,由shellcode產(chǎn)生一個shell,如果被攻擊程序設(shè)置了suid位,那么產(chǎn)生的shell就是root shell,黑客也就獲得了系統(tǒng)的最高控制權(quán),這一過程就是基本的緩沖區(qū)溢出攻擊。
覆蓋函數(shù)的返回地址是比較常見的攻擊方式,但緩沖區(qū)溢出攻擊的手法是靈活多樣的,往往在編程中的一個小小紕漏就可能導(dǎo)致被攻擊,下面簡單介紹一下幾種較為高級的攻擊方式。
�。�1)通過覆蓋函數(shù)指針進(jìn)行攻擊:
/* vulprog */
int main(int argc , char * argv[])
{
void (* fp)(char *) = (void (*)(char *))&puts;
char buff[256];
strcpy(buff,argc[1]);
fp(argc[2]);
exit(1);
} |
上面這個程序在執(zhí)行拷貝時沒有檢查邊界,這樣用戶數(shù)據(jù)就有可能覆蓋函數(shù)指針fp,如果用shllcode的地址去覆蓋fp,那么函數(shù)指針調(diào)用時就會去執(zhí)行shellcode.
這種覆蓋函數(shù)指針的方式是一種較直接的覆蓋方式(因?yàn)楹瘮?shù)指針就在緩沖區(qū)上面),還有一種間接的覆蓋方式,就是當(dāng)函數(shù)指針不直接在緩沖區(qū)上面時,通過覆蓋另外一個指針來覆蓋函數(shù)指針,再將shellcode的地址填充函數(shù)指針。
�。�2)通過覆蓋 .dtors區(qū)地址進(jìn)行攻擊:
/* vulprog */
int main(int argc ,char * argv[])
{
char * pbuf = malloc(strlen(argv[2])+1);
char buff[256];
strcpy(buff,argv[1]);
strcpy(pbuf,argv[2]);
exit(1);
} |
雖然這個程序沒有函數(shù)指針,但在執(zhí)行第二個拷貝時,可以將任意的數(shù)據(jù)拷貝到任意的地址中(這個地址由第一個拷貝指定),這時就可以選擇用 .dtors區(qū)的地址覆蓋指針pbuf,在執(zhí)行第二個拷貝時將shellcode的地址拷貝至。dtors區(qū),那么在函數(shù)退出時shellcode就會被執(zhí)行。其實(shí)針對這個程序,攻擊者不僅可以覆蓋。dtors區(qū)的地址,還可以覆蓋GOT(全局偏移表)中exit的地址,或__deregister_frame_info的地址。
從上面的這些例子可以看出,如果編程中不注意緩沖區(qū)邊界的檢查,就很可能導(dǎo)致被溢出攻擊。
由于緩沖區(qū)溢出攻擊的頻繁爆發(fā),迫使很多操作系統(tǒng)廠商推出了不可執(zhí)行堆棧、更新C庫函數(shù)等措施。這些措施一定程度上遏制了普通的緩沖區(qū)溢出,但道高一尺,魔高一丈,黑客們很快就將注意力轉(zhuǎn)移到新的溢出攻擊上,如堆溢出。從最初的溢出重要變量(如函數(shù)指針、文件指針)到dlmalloc中malloc-free類型的堆溢出到ptmalloc中的堆溢出,層出不窮。其實(shí)不管這些手法有多高明,最終的根源只有一個:利用程序中未對緩沖區(qū)邊界進(jìn)行有效檢查。
2.SQL注入
數(shù)據(jù)庫系統(tǒng)除了可能受到緩沖區(qū)溢出的攻擊外,近幾年又出現(xiàn)了SQL注入的攻擊方式,這種攻擊方式被稱為 “ SYSDBA的惡夢”。SQL注入可能導(dǎo)致數(shù)據(jù)庫系統(tǒng)中的普通用戶竊取機(jī)密數(shù)據(jù)(如獲得SYSDBA密碼)、進(jìn)行權(quán)限提升(如獲得SYSDBA特權(quán))等,而這種攻擊方式又不需要太多計算機(jī)方面的知識,一般只要能熟練使用SQL語言即可,因此對數(shù)據(jù)庫的安全構(gòu)成了很大的威脅。
SQL注入的攻擊方式比較簡單,一般是將一些特權(quán)語句注入到有漏洞的存儲過程或觸發(fā)器中導(dǎo)致這些語句被非法執(zhí)行。例如在Oracle中由SYS創(chuàng)建如下存儲過程并將執(zhí)行權(quán)限授予普通用戶:
CREATE OR REPLACE PROCEDURE PROC1 ( INPUT VARCHAR2) AS ... ...
STMT:='SELECT TITLES FROM BOOKS WHERE AUTHOR =''' || INPUT || '''';
EXECUTE IMMEDIATE STMT;
... ... |
正常情況下用戶可以通過執(zhí)行:EXEC SYS.PROC1('DICKENS')來查詢DICKENS的著作,但如果惡意用戶這樣執(zhí)行該存儲過程:
EXEC SYS.PROC1( 'DICKENS'' UNION SELECT PASSWORD FROM USERS_TABLE WHERE ''A'' = ''A'),那么他就非法地查出了所有用戶的密碼。
雖然這只是一個簡單的例子,但它表明在編寫系統(tǒng)存儲過程、函數(shù)和觸發(fā)器時一定要注意防止SQL注入的可能。數(shù)據(jù)庫是信息系統(tǒng)的基石,一旦被黑客入侵,后果將不堪設(shè)想。而抵抗黑客入侵的最好辦法就是克服軟件編程中存在的各種漏洞,讓黑客無機(jī)可乘。通過源碼審計、漏洞跟蹤等方式可以較好的修正現(xiàn)存系統(tǒng)中的各種安全隱患。目前我們正在達(dá)夢數(shù)據(jù)庫中積極開展漏洞發(fā)掘的相關(guān)工作,努力使達(dá)夢數(shù)據(jù)庫成為真正牢不可破的數(shù)據(jù)庫,為國家的信息安全構(gòu)筑堅強(qiáng)的基石。
|