2008-12-30 93 views
3

Windows系統中的「格式字符串漏洞」到底是什麼,它是如何工作的,以及如何防範它?防止格式化字符串漏洞

+0

那麼,知道如何攻擊有助於瞭解如何防禦/避免漏洞。這就是公開披露這些漏洞/漏洞的想法。 – PhiLho 2008-12-30 16:10:44

回答

2

在用戶輸入某些字符此僞代碼被打印,像「你好」

string s=getUserInput(); 
write(s) 

即如預期工作。但由於寫入可以格式化字符串,例如

int i=getUnits(); 
write("%02d units",i); 

輸出:「03單位」。如果用戶在第一個地方寫了「%02d」,那麼...因爲堆棧中沒有參數,其他的東西都會被提取。那是什麼,如果這是一個問題,則取決於該計劃。

一個簡單的辦法是將程序告訴輸出字符串:

write("%s",s); 

或使用不嘗試格式化字符串的另一種方法:

output(s); 

一個link到維基百科更多信息。

4

格式字符串攻擊,在其最簡單的,是這樣的:

char buffer[128]; 
gets(buffer); 
printf(buffer); 

那裏面有一個緩衝區溢出漏洞爲好,但問題是這樣的:你傳遞不受信任的數據(從用戶)到printf(或它的一個表兄弟)使用該參數作爲格式字符串。

也就是說:如果用戶輸入「%s」,就會產生信息泄露漏洞,因爲printf會將用戶輸入視爲格式字符串,並嘗試在堆棧上打印下一個內容作爲一個字符串。就好像你的代碼是printf("%s");。由於您沒有將任何其他參數傳遞給printf,它會顯示任意的內容。

如果用戶輸入「%n」,則可能會發生特權攻擊(至少拒絕服務攻擊)的潛在提升,因爲%n格式字符串會導致printf寫入打印的字符數遠離堆棧上的下一個位置。既然你沒有給它一個放置這個值的地方,它會寫入任意的地方。

這一切都很糟糕,並且是使用printf和堂兄弟時應該特別小心的一個原因。

你應該做的是這樣的:

printf("%s", buffer); 

這意味着,用戶在輸入時從來沒有像格式字符串處理,所以你從那個特定的攻擊向量安全。

在Visual C++中,您可以使用__Format_string註釋來告訴它驗證參數爲printf%n默認是不允許的。在GCC中,您可以使用__attribute__(__printf__)來做同樣的事情。