c語言代碼審計規范


 


 

 

目錄

1. 緩沖區溢出漏洞... 2

1.1 get函數溢出漏洞... 2

1.2 strcpy函數溢出漏洞... 2

1.3 sprintf函數溢出漏洞... 3

1.4 printf字符串格式攻擊漏洞... 3

1.5 scanf函數溢出漏洞... 3

2 指針覆寫... 4

2.1命令注入... 4

3 存儲越界... 5

3.1 數組元素沒有進行邊界檢查... 5

3.2 指針加下標的元素沒有進行邊界檢查.... 5

3.3 數值型變量范圍表示范圍越界... 6

4 動態存儲分配... 6

4.1 內存分配和釋放函數沒有正確配對... 7

4.2 重復釋放同一內存空間... 7

4.3 釋放連續內存空間的順序錯誤... 8

5 內存泄露... 8

5.1 未釋放動態申請的內存地址空間... 8

5.2 動態申請的內存地址空間釋放順序錯誤... 9

 

 

 

 

 

 

 

 

 

 

 

 

1. 緩沖區溢出漏洞

介紹:

程序向緩沖區寫入了超過緩沖區最大能保存的數據。當黑客用精心構造的數據覆蓋函數返回值,等到函數返回時,就會去黑客覆蓋的返回值地址去執行事先安排好的攻擊代碼。

1.1 get函數溢出漏洞

介紹:

gets()函數不檢查緩沖長度,調用gets(buffer),會把用戶輸入的內容放在buffer中,但是對這個內容沒有檢查長度,如果用戶輸入的內容過長,就會覆蓋在buffer之后定義的變量,也就是用戶可以隨意更改一些程序中的變量。

審計策略:

全局搜索gets函數

修復建議:

使用fgets()函數,首先要用malloc為buffer分配一部分固定的空間。然后調用fgets()的時候傳遞進去預計長度的值,這樣就不會造成溢出了

1.2 strcpy函數溢出漏洞

介紹:

strcpy函數是復制字符串的,接受兩個參數一個是被復制字符串,一個是新字符串。這個家族有三個函數:strcpy,strcat,strcmp,都有溢出問題。因為不檢查長度

審計策略:

全局搜索strcpy,strcat,strcmp這三個函數

修復建議:

建議一:在使用這三個函數函數前加入檢查長度的語句。

建議二:使用strncpy,strncat,strncmp,這三個是會檢查長度的,但是存在的問題是,如果截取了長度,不能保證字符串以'\0'結尾,所以可能需要添加一些代碼進行判斷。

1.3 sprintf函數溢出漏洞

介紹:

sprintf函數打印到字符串中,對長度不做檢查,造成溢出。

審計策略:

全局搜索sprintf()函數

修復建議:

使用snprintf()函數,這個函數不僅能夠避免緩沖區溢出(檢查長度),還能返回傳遞字符串的長度,以供判斷是否需要處理截取后的'\0'結尾問題。

1.4 printf字符串格式攻擊漏洞

介紹:

這一類的漏洞與字符串格式攻擊相關,也就是我們常說的利用格式化字符串漏洞進行攻擊。這種攻擊通常會導致信息泄露、覆蓋內存(%n)等等。這個漏洞可以被以下函數觸發:printf, fprintf, sprintf以及snprintf。這些函數的共同特點就是,都以格式化的字符串作為參數,即百分號之后的格式約定。

審計策略:

全局搜索printf, fprintf, sprintf以及snprintf這些函數。

修復建議:

硬編碼格式化字符串

1.5 scanf函數溢出漏洞

介紹:

scanf是輸入函數,由於對輸入長度沒有控制導致緩沖區溢出問題,通類型有scanf,fscanf,sscanf

審計策略:

全局搜索scanf,fscanf,sscanf

修復建議

使用精度說明符,或自己進行解析

2 指針覆寫

介紹:

指針覆寫漏洞是指由於對指針沒有進行很好的處理和保護,造成指針的值被修改和利用的漏洞。其中利用的方式有代碼注入攻擊,返回函數攻擊,返回導向編程。

利用指針覆寫實施攻擊需要滿足兩個條件:
1)程序中存在緩沖區溢出漏洞。
2)發生溢出錯誤的緩沖區要和被覆寫的指針在同一內存段內,且位置最好相鄰。

2.1命令注入

介紹:

執行命令時,命令將未驗證的用戶輸入作為命令參數的一部分,導致應用可能遭受攻擊。分為三個階段,(1)不可信的數據通過用戶進入程序。(2)數據被程序作為運行的命令的一部分執行。(3)通過執行命令,程序就會給攻擊者本身不具有的特權或者能力。

漏洞示例一:

 int main(char* argc,char**argv){

     char cmd[CMD_MAX]="/usr/bin/cat";

     strcat(cmd,argv[1]);

     system(cmd);<br>//1,當用戶輸入標准的文件名,程序能正常工作。

     //2,當用戶輸入“;rm -rf/"將刪除根分區的所有文件和內容。

}

漏洞示例二:

    char* home =getenv("APPHOME");

    char*cmd=(char*)malloc(strlen(home)+strlen(INITCCMD));

    if(cmd){

        strcpy(cmd,home);

        strcat(cmd,INITCMD);

        execl(cmd,NULL);

    //從系統中取出的變量正確的時候,程序正常運行

    //攻擊者變化系統變量,變量進入命令,造成命令注入攻擊。}

審計策略:

全局搜索cmd,malloc等關鍵詞看是否對接受參數進行限制,對用戶是否進行驗證。

3 存儲越界

介紹:

存儲越界指一個變量讀或寫超出變量分配的內存空間,c語言編譯器沒有提供數組和緩沖區的邊界檢查,他對字符串的操作只是通過識別‘\0’來判斷是否到達該字符串的結尾,這樣很容易造成訪問越界問題,如果越界讀數據,就會得到一些無用信息甚至受到黑客的攻擊,導致程序運行出錯或者以訪問非法內存而終止程序。

3.1 數組元素沒有進行邊界檢查

介紹:

這類漏洞主要針對顯示的使用數組元素,包括基本類型和用戶自定義類型的數組操作。

漏洞示例

    vector<type>phone_book(5);

    for(i=1;i<6;i++)phone_book[i]="abc";

 

    //由於編譯器不會對for循環中的phone_book的引用進行邊界檢查,就會出現安全漏洞

漏洞示例

    int day[]={1,2,3,4,5,6,7};

    day[8]=8;

    //對數組day的引用day[8]將超出數組的聲明范圍。

審計策略:

搜索關於數組的關鍵詞,定位數組。

修復建議:

進行邊界檢查,包括數組,字符串和數值類型等。

3.2 指針加下標的元素沒有進行邊界檢查

介紹:

該漏洞和3.1很相似,但指針可以指向數組也可以指向單個元素。它屬於隱式的使用數組元素。

漏洞示例:

    int array[] ={1,2,3};

    int*p=&array[0];

    p[-1]=0;

    *(p+3)=4;

    //對數組array和指針p定義,使指針p指向array首地址,數組array的地址范圍

    //限制p的指向也有一定的范圍,但是p指向的空間超出了原來所指范圍,所以會出現

    //安全漏洞。

審計策略:

定位有關指針,數組等關鍵詞

修復建議:

對指針加下標元素進行邊界檢查

3.3 數值型變量范圍表示范圍越界

介紹:

數值型變量都有一個表示范圍,如果對變量不加限制的進行相互操作就很容易導致范圍越界。

漏洞示例:

    short int var =30000+30000;

    //short int表示的范圍是-32769~32769,此時var的值超過了short int 的表示范圍

    //系統會進行自動轉換,其結果和實際語義不符。

4 動態存儲分配

介紹:

靜態存儲分配對變量進行定義聲明時編譯器就能獲取它 們所需存儲空間的大小,並為其分配相應的內存空間,而且在 其生存期內是固定不變的,生存期結束后系統對其自動釋放。 動態存儲分配相對於靜態存儲分配,它是在程序執行期間,通 過申請分配指定的內存空間或釋放指定的內存空間。C語言和 C++語言都提供各自的動態分配方法,C語言提供的是幾個庫 函數:malloc, relealloe,free等,而C++語言提供的是運算 符:new , new[], delete,deleteQ等等。這些庫函數和運算符都用於 動態申請或釋放內存,並且C++編譯器對函數和運算符都能識 別,所以對程序員來說很容易混淆使用,最終造成程序運行錯 誤。此外,由於是動態分配,程序員很難控制分配空間的次數是 否與釋放空間的次數相等,而編譯器對這些問題都不提供檢 查,所以也會出現對同- - 空間釋放多次或使用已釋放空間等這 樣的安全漏洞。

4.1 內存分配和釋放函數沒有正確配對

介紹:

從內存分配的機理上來說,malloc和free配對,new和delete. 配對, new[]和delete[]配對。因為malloc/free是庫函數而不是運 算符,它們只負責分配或釋放一-塊連續的內存空間,不執行構 造/析構函數。而new/delete是C++的運算符,它在完成分配空 間的同時自動執行了構造/析構函數,它主要用於非基本數據 類型對象的操作。new[]/delete[]是用 來同時分配/釋放對象數 組。這些運算符或函數不能混合使用,否則將出現安全漏洞。

漏洞示例:

    S1:int*p=(int*)malloc(sizeof(int));

    S2: *p=100;

    S3: delete p;

    //語句S1用malloe函數為p動態申請空間,而語句S3使用運算符delete來釋放p,

     // 顯然兩者沒有正確配對,最終出現安全漏洞。

4.2 重復釋放同一內存空間

介紹:

由於編譯器沒有分析別名引起的漏洞。

    char*p, *q;

    S1:p=( char* )malloc( sizeof( char)* 10);

    S2: strcpy(p, "hello");

    S3:q=p;

    S4: strcpy(q,"world");

    S5:free(p);

    S6: free(q);

    //這個例子中語句S1為p動態分配了空間,語句S3使指針q指向p所指的空間,這時指

    // 針p,q已成為指針別名,但是編譯器無法檢查出,以致於編譯到語句S5,S6仍然不能

    //  報錯,這為程序運行帶來了隱患。同樣如果程序中通過對象間賦值而該類對象的構造

    //  函數動態申請空間,析構函數動態釋放空間,這樣也可能引起安全漏洞:或者兩個動態

    //  申請的對象,通過相互賦值導致某一對象指向的空間被釋放多次:也可能是由於拷貝構

    //  造函數使指針成員指向的空間被釋放多次等等,這些都屬於編譯器缺少別名檢查最終導

    //  致同一內存重復釋放。

4.3 釋放連續內存空間的順序錯誤

介紹:

malloc或new[]都是用來動態申請一塊連續的空間,包括 基本類型和對象類型,釋放時必須對空間整體釋放,而不能單 獨釋放某個空間,即釋放時指向連續空間的指針必須在分配空 間的首部,否則對連續申請的內存空間不能正確釋放。

漏洞示例:

    int*p=( int* )malloc( sizeof( int)* 10);

    while(i<l0){*p=i*i;i++:p++;}

    free(p);

    //指針p不能被正確釋放,因為釋放時指針p沒有返回到申請空間的頭部。

審計策略:

定位指針,malloc等關鍵字進行排查

5 內存泄露

介紹:

常說的內存泄漏是指堆內存的泄漏。堆內存是指程序從堆 中分配、大小任意、使用完后必須顯式釋放的內存。應用程序一 般使用malloe, realloe,new等操作從堆中分配一塊內存,使用 完后程序必須負責調用相應的free或delete釋放該內存塊,否 則,這塊內存就不能被再次使用,即出現內存泄漏

5.1 未釋放動態申請的內存地址空間

介紹:

使用malloc, realloc , alloc, new, new[]等動態申請對象(包括 基本類型和自定義類型的對象)空間,但最后沒有對其進行相 應的空間釋放。

漏洞示例:

    while( i<MAX ){

    p=( double* )malloc( sizeof( double));

    *p=pow(x,i):

    i++;

    free(p):

    //循環體中對MAX-1個對象進行了動態分配空間,但最后只對一個進行釋放,前面的MAX-2個對象的空間將被泄漏。

審計策略:

定位malloc, realloc , alloc, new, new[]等進行查看是否對其進行相應的空間釋放。

5.2 動態申請的內存地址空間釋放順序錯誤

介紹:

這類漏洞主要針對多維數組的釋放順序,或指針結構體中 含有指針成員以及循環體釋放內存空間的不正確引起的。

漏洞示例:

    typedef struct forest{

    int tnum;

    tree*t://tree也是一個結構體

    }forest:

    forest*f= new forest[2]:

    for(i=0;i<2;i++){

    (f+i)->tnum=i;

    (f+i)->l=new tree[(J+i )- >tnum];

    delete f;

 

    //在沒有釋放forest結構體內的指針t時就先釋放f,這樣為t分配的空間將被泄漏。對於多級連續內存空間的分配

    //是先申請大范圍空間,再申請小范圍空間,釋放空間則相反應先釋放小范圍空間再釋放大范圍空間,否則如例所示

    //將出現內存泄漏。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM