錯誤 #10 (Silverlight CLR C#)
bool verifyCode(string discountCode) {
// We store the hash of the secret code instead of
// the plaintext of the secret code.
// Hash the incoming value and compare it against
// the stored hash.
SHA1Managed hashFunction = new SHA1Managed();
byte[] codeHash =
hashFunction.ComputeHash(
System.Text.Encoding.Unicode.GetBytes(discountCode));
byte[] secretCode = new byte[] {
116, 46, 130, 122, 36, 234, 158, 125, 163, 122,
157, 186, 64, 142, 51, 153, 113, 79, 1, 42 };
if (codeHash.Length != secretCode.Length) {
// The hash lengths don't match, so the strings don't
// match this should never happen, but we check anyway
return false;
}
// perform an element-by-element comparison of the arrays
for (int i = 0; i < codeHash.Length; i++) {
if (codeHash[i] != secretCode[i])
return false; // the hashes don't match
}
// all the elements match, so the strings match
// the discount code is valid, inform the server
WebServiceSoapClient client = new WebServiceSoapClIEnt();
clIEnt.ApplyDiscountCode();
return true;
}
答案:開發人員做出了一個明智決定,不在代碼中嵌入純文本形式的加密代碼。如果您只需測試用戶是否知道機密內容(如折扣代碼或密碼),存儲該機密內容的哈希值並比較哈希值肯定要比存儲純文本並直接比較字符串要好一些。遺憾的是,開發人員選擇了使用 SHA-1 哈希算法,它暴露出了嚴重的問題,之後被 SDL 禁止。更好的選擇是使用 SHA256Managed 類,它可以實現經 SDL 批准和推薦的 SHA-256 哈希算法。如果您發現了這一點,則加一分。
比選擇 SHA-1 而不是 SHA-256 還要糟糕的是開發人員忽略了對哈希值進行處理。未經處理的哈希值非常容易通過預先計算的哈希表(通常稱為彩虹表)破解。攻擊者可能在很短的時間內便可從未經處理的哈希值判斷出原始的純文本加密代碼。(作者將在 SDL 博客中發表賀詞,以感謝第一個使用純文本加密代碼響應我們號召的人。)如果您捕獲了未經處理的哈希值,則給自己加一分。
但是,此代碼存在的最大問題在於它竟然在客戶端計算機上執行!要記得我們開頭所說的,是 Silverlight CLR 代碼在用戶的浏覽器中運行。在客戶端上運行的任何代碼都可能被攻擊者所操控。無需多言。對於鐵了心的用戶,沒有什麼能阻止他在運行 Silverlight 代碼的浏覽器實例中附加調試程序並在代碼執行時單步調試它。
他可以將 codeHash 變量設置為等於 secretCode 哈希值,這樣一來比較邏輯始終都會成功。或者他可以完全略過驗證邏輯,直接跳到應用折扣代碼的 Web 服務調用的當前指令處。最簡單的方式是,他可以完全避開調試程序,只需直接調用 Web 服務方法 ApplyDiscountCode!
必須要知道,即使您可以使用 C# 或 Visual Basic 來創建 Silverlight 應用程序(就像您處理 ASP.Net Web 窗體那樣),Silverlight 代碼也是在客戶端計算機上運行,而 Web 窗體代碼是在服務器上運行。在客戶端上運行的代碼可能會被攻擊者查看和篡改。絕不要將機密內容嵌入到客戶端代碼中,或允許客戶端代碼執行特權決策(諸如折扣代碼是否有效,或是否授權用戶執行某個操作)。如果您捕獲了此錯誤,則給自己加一分。