1. 程式人生 > >數據庫安全知識介紹

數據庫安全知識介紹

不堪 環境 退出 有效 ble 發現 地址 數據庫系統 拷貝

數據庫系統是在操作系統平臺之上的最重要的系統軟件,數據庫系統的安全可以說是十分重要的。曾經有句話這樣說:如果網絡遍地是金錢,那麽金錢就在數據庫服務器中。隨著無紙化業務環境的不斷擴大,人們在數據庫中存儲著越來越多的敏感信息:銀行賬戶、醫療記錄、政府文件、軍事機密等等,數據庫系統就成為越來越有價值的攻擊目標,因此確保數據庫系統的安全也越來越重要。

  作為一種大型的系統軟件,數據庫系統中也存在著各種各樣的安全漏洞,其中危害性較大的有緩沖區溢出、堆溢出和SQL註入等。

  1.緩沖區溢出

  緩沖區溢出是一種很常見也很古老的安全漏洞。早在上個世紀80年代,緩沖區溢出就已經為人所知,但時至今日,大量的緩沖區溢出漏洞仍被發現。最著名的Morris蠕蟲就是利用Unix系統上fingerd程序的緩沖區溢出漏洞。在Oracle 9i發布之初,Oarcle公司曾宣稱他的數據庫是“ unbreakable ”的,但不到幾個月的時間,就暴出Oracle 9i中oracle.exe、XDB等程序存在多個緩沖區溢出漏洞。

  在C語言中最常見的緩沖區就是字符數組,而操縱字符數組的函數有gets、strcpy、sprintf等。這些函數在執行字符串拷貝的過程中沒有對字符串進行長度檢查,這樣就很容易發生超長的字符串溢出緩沖區的情況。當初這樣設計是出於效率的考慮,但現在看來,這些函數的使用已成為C語言軟件脆弱的一個重要因素。如果程序員沒有良好的編程習慣,時刻註意函數調用過程中是否拷貝了超過緩沖區長度的字符串,那麽緩沖區溢出就不可避免。對於一個有緩沖區溢出漏洞的程序,當普通用戶輸入超長字符串時,通常只會使該程序崩潰。例如對於下面一小段代碼:

  以下是引用片段:

  

   /* vulprog */

  #include

  int main(int argc , char * argv[])

  {

  char buff[8];

  strcpy(buff, argv[1]);

  }

  如果用戶執行 ./vulprog AAAAAAAAAAAAAAAA,在Linux上會出現段錯誤,因為用戶輸入了超長的字符串,除了填滿了緩沖區,還覆蓋了其他一些程序正常退出所需要的數據。為了研究這個問題,就需要了解Linux系統中進程的內存空間。

  進行函數調用時系統所作的“序幕”工作就是將函數的返回地址和EBP壓棧,再將ESP賦給EBP使其成為局部基指針,最後ESP減去一定的值為局部變量留出空間。這樣當程序將過長的字符串拷貝到緩沖區時就會依次覆蓋EBP和返回地址。當用AAAA覆蓋返回地址,函數退棧時系統就將0x41414141(A的16進制ASCII碼)賦給EIP去執行,由於是一個非法的內存地址,故程序崩潰。但如果用一個實際存在的地址覆蓋返回地址,那麽程序就轉而去執行該地址處的指令,通常黑客會在這個地址植入所謂的shellcode,由shellcode產生一個shell,如果被攻擊程序設置了suid位,那麽產生的shell就是root shell,黑客也就獲得了系統的最高控制權,這一過程就是基本的緩沖區溢出攻擊。

  覆蓋函數的返回地址是比較常見的攻擊方式,但緩沖區溢出攻擊的手法是靈活多樣的,往往在編程中的一個小小紕漏就可能導致被攻擊,下面簡單介紹一下幾種較為高級的攻擊方式。

  (1)通過覆蓋函數指針進行攻擊:

  以下是引用片段:

  

   /* 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);

  }

  上面這個程序在執行拷貝時沒有檢查邊界,這樣用戶數據就有可能覆蓋函數指針fp,如果用shllcode的地址去覆蓋fp,那麽函數指針調用時就會去執行shellcode。

  這種覆蓋函數指針的方式是一種較直接的覆蓋方式(因為函數指針就在緩沖區上面),還有一種間接的覆蓋方式,就是當函數指針不直接在緩沖區上面時,通過覆蓋另外一個指針來覆蓋函數指針,再將shellcode的地址填充函數指針。

  (2)通過覆蓋 .dtors區地址進行攻擊:

  以下是引用片段:

  

   /* 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);

  }

  雖然這個程序沒有函數指針,但在執行第二個拷貝時,可以將任意的數據拷貝到任意的地址中(這個地址由第一個拷貝指定),這時就可以選擇用 .dtors區的地址覆蓋指針pbuf,在執行第二個拷貝時將shellcode的地址拷貝至.dtors區,那麽在函數退出時shellcode就會被執行。

  其實針對這個程序,攻擊者不僅可以覆蓋.dtors區的地址,還可以覆蓋GOT(全局偏移表)中exit的地址,或__deregister_frame_info的地址。

  從上面的這些例子可以看出,如果編程中不註意緩沖區邊界的檢查,就很可能導致被溢出攻擊。

  由於緩沖區溢出攻擊的頻繁爆發,迫使很多操作系統廠商推出了不可執行堆棧、更新C庫函數等措施。這些措施一定程度上遏制了普通的緩沖區溢出,但道高一尺,魔高一丈,黑客們很快就將註意力轉移到新的溢出攻擊上,如堆溢出。從最初的溢出重要變量(如函數指針、文件指針)到dlmalloc中malloc-free類型的堆溢出到ptmalloc中的堆溢出,層出不窮。其實不管這些手法有多高明,最終的根源只有一個:利用程序中未對緩沖區邊界進行有效檢查。

  2.SQL註入

  數據庫系統除了可能受到緩沖區溢出的攻擊外,近幾年又出現了SQL註入的攻擊方式,這種攻擊方式被稱為 “ SYSDBA的惡夢”。SQL註入可能導致數據庫系統中的普通用戶竊取機密數據(如獲得SYSDBA密碼)、進行權限提升(如獲得SYSDBA特權)等,而這種攻擊方式又不需要太多計算機方面的知識,一般只要能熟練使用SQL語言即可,因此對數據庫的安全構成了很大的威脅。

  SQL註入的攻擊方式比較簡單,一般是將一些特權語句註入到有漏洞的存儲過程或觸發器中導致這些語句被非法執行。例如在Oracle中由SYS創建如下存儲過程並將執行權限授予普通用戶:

  以下是引用片段:

  

   CREATE OR REPLACE PROCEDURE PROC1 ( INPUT VARCHAR2) AS

  ... ...

  STMT:=‘SELECT TITLES FROM BOOKS WHERE AUTHOR =‘‘‘ || INPUT || ‘‘‘‘;

  EXECUTE IMMEDIATE STMT;

  ... ...

  正常情況下用戶可以通過執行:EXEC SYS.PROC1(‘DICKENS‘)來查詢DICKENS的著作,但如果惡意用戶這樣執行該存儲過程:

  EXEC SYS.PROC1( ‘DICKENS‘‘ UNION SELECT PASSWORD FROM USERS_TABLE WHERE ‘‘A‘‘ = ‘‘A‘),那麽他就非法地查出了所有用戶的密碼。

  雖然這只是一個簡單的例子,但它表明在編寫系統存儲過程、函數和觸發器時一定要註意防止SQL註入的可能。

  數據庫是信息系統的基石,一旦被黑客入侵,後果將不堪設想。而抵抗黑客入侵的好辦法就是克服軟件編程中存在的各種漏洞,讓黑客無機可乘。通過源碼審計、漏洞跟蹤等方式可以較好的修正現存系統中的各種安全隱患。目前我們正在達夢數據庫中積極開展漏洞發掘的相關工作,努力使達夢數據庫成為真正牢不可破的數據庫,為國家的信息安全構築堅強的基石。

  

數據庫安全知識介紹