跳至內容

安全程式碼撰寫

本頁使用了標題或全文手工轉換
維基百科,自由的百科全書

安全程式碼撰寫(Secure coding)是依照安全指引開發電腦軟體,避免引入漏洞的軟體開發實務。設計缺陷、程序錯誤及邏輯謬誤是最常被利用軟體漏洞的主要原因[1]。若識別出這些不安全的程式碼撰寫實務,教育程式設計師改用較安全的軟體寫法,組織可以有主動的措施,在程式佈置之前就消除或大幅減少軟體漏洞[2]

有些研究者建議,為了有效的面對網路安全相關的威脅,應該在程式碼撰寫時加入適當的安全性。若在軟體設計時就已考慮安全性,這可以避免內部人士的攻擊,也減少和應用程式安全有關的威脅[3]

避免緩衝區溢出

緩衝區溢出是常見的軟體安全漏洞,若程序要在固定長度的緩衝區儲存超過其大小的資料,就會出現此一問題。例如,有8個位置可以儲存資料,但程式卻試著要儲存9個資料,就會出現問題。緩衝區溢出會覆寫到鄰近位置的記憶體,造成安全漏洞(棧緩衝區溢出)或是程式中止執行(例如出現記憶體區段錯誤[1]

以下是一個容易出現緩衝區溢出的C語言程式例子


int vulnerable_function(char * large_user_input) {
    char dst[SMALL];
    strcpy(dst, large_user_input);
}

若使用者輸入的資料比緩衝區的大小要大,就會出現緩衝區溢出。

若要修正此一問題,可以用strncpy來避免緩衝區溢出

int secure_function(char * user_input) {
    char dst[BUF_SIZE];
    // copy a maximum of BUF_SIZE bytes
    strncpy(dst, user_input, BUF_SIZE);
}

另一種作法是用malloc英語malloc指令,在heap裡動態分配記憶體

char * secure_copy(char * src) {
    size_t len = strlen(src);
    char * dst = (char *) malloc(len + 1);
    if (dst != NULL) {
        strncpy(dst, src, len);
        // append null terminator 
        dst[len] = '\0';
    }
    return dst;
}

在上述的程式片段裡,程式設法將src的內容複製到dst,不過也會檢查malloc的傳回值,確定有足夠的記憶體可以分配記憶體給dst。

避免格式字串攻擊

格式字串攻擊英語Format string attacks是惡意用戶在輸入一些會提供給格式設定函式(如printf())的資料時,輸入特殊的內容,讓函式的動作異常。此攻擊會破壞性的讀取或寫入呼叫堆疊

C語言的printf函式會將輸出寫到stdout。若其引數的格式有誤時,會造成一些嚴重的安全錯誤。以下是一個格式字串攻擊的例子。

int vulnerable_print(char * malicious_input) {
	printf(malicious_input);
}

像是"%s%s%s%s%s%s%s"就屬於惡意輸入,會因為不正確的記憶體讀取而讓程式崩潰。

避免整數溢位

整數溢位會出現在整數運算的結果太大,用規劃的記憶體空間無法正確表示的情形。若程式沒有檢查整數運算的結果,設法避免整數溢位,可能會造成軟體錯誤或是漏洞。

以下是C++的函式,原始目的是要確認x和y相加的結果小於等於已定義好的數值MAX:

bool sumIsValid_flawed(unsigned int x, unsigned int y) {
	unsigned int sum = x + y;
	return sum <= MAX;
}

這段程式的問題是在進行整數的加法之後才進行檢查。若x和y的和大於unsigned int可以表示的最大值,在進行加法之後就已出現溢位,因此雖然x和y的和大於MAX,但是其溢位後的結果可能會小於MAX。

以下也是檢查溢位的程式,加上了檢查x和y的和是否有大於等於x,y二個數值的判斷,因為x和y是無號數整數,二者的和不會小於其中的任一數字。若是若計算出來的和小於任一數字,就代表已經溢位了。

bool sumIsValid_secure(unsigned int x, unsigned int y) {
	unsigned int sum = x + y;
	return sum >= x && sum >= y && sum <= MAX;
}

避免目錄遍歷

目錄遍歷是由不可靠來源提供的路徑產生的漏洞,該路徑造成了未授權的伺服器目錄或是檔案存取。

例如,考慮一個接受檔案名稱,讀取文章的腳本,腳本會讀檔案名稱輸入,之後進行處理。這樣腳本可能會用類似以下的的URL 來找有關dog food的文章。

https://www.example.net/cgi-bin/article.sh?name=dogfood.html

若此腳本沒有輸入檢查,相信使用者輸入的檔案都是有效的,惡意使用者可能會產生以下的URL來取得網站伺服器的組態:

https://www.example.net/cgi-bin/article.sh?name=../../../../../etc/passwd

若是在類Unix系統中,這可能會洩漏/etc/passwd檔,其中包括了用戶ID用戶名稱家目錄路徑等。(SQL注入也是類似情境下的攻擊)。

相關條目

參考資料

  1. ^ 1.0 1.1 Viega, John; Gary McGraw. Building Secure Software: How to Avoid Security Problems the Right Way. MAddison-Wesley Professional. 2001: 528. ISBN 978-0201721522. 
  2. ^ Taylor, Blair; Azadegan, Shiva. Threading secure coding principles and risk analysis into the undergraduate computer science and information systems curriculum. Proceedings of the 3rd annual conference on Information security curriculum development. InfoSecCD '06. Kennesaw, Georgia: Association for Computing Machinery. 2006-09-22: 24–29. ISBN 978-1-59593-437-6. S2CID 2452783. doi:10.1145/1231047.1231053. 
  3. ^ Russell L, Jones. Secure Coding: Building Security into the Software Development Life Cycle. Information Systems Security. Dec 2004. ProQuest 229507883. 

參考書目

  • Taylor, Art; Brian Buege; Randy Layman. Hacking Exposed J2EE & Java. McGraw-Hill Primis. 2006: 426. ISBN 0-390-59975-1.