錯誤 #8 (C#)
public class CustomSessionIDManager : System.Web.Session State.SessionIDManager
{
private static object lockObject = new object();
public override string CreateSessionID(HttpContext context)
{
lock (lockObject)
{
Int32? lastSessionId = (int?)context.Application ["LastSessionId"];
if (lastSessionId == null)
lastSessionId = 1;
else
lastSessionId++;
context.Application["LastSessionId"] = lastSessionId;
return lastSessionId.ToString();
}
}
}
答案:這裡有兩個主要問題。雖然此代碼可以正確地對應用程序邏輯加一道鎖,從而確保兩個線程不會同時創建相同的會話 ID,但它仍然不能在服務器場中進行安全部署。HttpContext.Application 對象所引用的應用程序狀態並不在各個服務器之間共享。如果此應用程序已在服務器場中部署,則可能會導致會話 ID 沖突。如果您捕獲了此錯誤,則給自己加一分。
另一個嚴重的問題在於可以輕松猜出此類生成的會話 ID 是一個連續整數。如果某用戶看到了他的會話令牌並注意到其會話 ID 為 100,則該用戶可以使用簡單的浏覽器實用程序將會話 ID 改為 99 或 98 或其他任何更小的值,從而攔截這些用戶的會話。
在這種情況下,更適合開發人員的方案是使用 GUID 或其他較大的、隨機的字符串組合字母和數字。如果您意識到有序整數對會話 ID 令牌而言是糟糕的選擇,則您獲得一分。
錯誤 #9 (C#)
bool login(string username,
string passWord,
SqlConnection connection,
out string errorMessage) {
SqlCommand selectUserAndPassWord = new SqlCommand(
"SELECT PassWord FROM UserAccount WHERE Username = @username",
connection);
selectUserAndPassWord.Parameters.Add(
new SqlParameter("@username", username));
string validPassWord =
(string)selectUserAndPassWord.ExecuteScalar();
if (validPassWord == null) {
// the user doesn't exist in the database
errorMessage = "Invalid user name";
return false;
}
else if (validPassword != passWord) {
// the given passWord doesn't match
errorMessage = "Incorrect passWord";
return false;
}
else {
// success
errorMessage = String.Empty;
return true;
}
}
答案:此處最大的問題在於,當登錄失敗時,應用程序向用戶返回的信息過多。雖然對用戶來說,弄清到底是輸錯了密碼還是完全忘記了用戶名無疑很有幫助,但此信息也幫助了那些試圖對應用程序發起強力攻擊的攻擊者。盡管聽起來與常理相悖,但在此情況下還是不要提供幫助。如果登錄失敗則顯示“用戶名或密碼無效”等消息,而不是“用戶名無效”和“密碼無效”。
如果您發現了這一點,則加一分。如果您還記得應用程序不應在數據庫中存儲純文本密碼,再獎勵您一分;在這種情況下應存儲和比較經過處理的密碼哈希值。
那麼該如何評定結果呢?
分數 評論 15+ 我們的理想人選。 11-14 還不錯吧,應該說很不錯。現在將您的才干應用到您的搭檔編寫的所有代碼中。 7-10 嗯。還不錯。您無疑還有一些方面需要學習,但是要比現在編寫 Web 應用程序的其中 50% 的開發人員強一些。 4-6 您有很多方面需要學習。請到您喜歡的書店購買本文兩位作者撰寫的全部書籍。 0-3 退出編輯器和編譯器,以免任何人受到傷害。