昨天我因為我網站(http://freesms.cloudapp.net )收到了惡意攻擊,我發布了ASP.NET網站限制訪問頻率一文,引起了部落格園各位高手的激烈討論,很多朋友朋友提出了一些疑問與改進意見,我感到非常開心。後來我也繼續思考了很多,現將我的想法寫下來,希望高手們再來看看,不吝賜教。o(∩_∩)o
在眾多網友中,最需要感謝的是在部落格園網友王瑋。你的由“ASP.NET網站限制訪問頻率”想到的兩點問題 一文中,提到了兩個問題:第一是驗證碼不能夠明文存在Cookie中;第二是IP地址可以欺騙某些驗證方式。
這兩個問題非常好,非常感謝 。 第一個問題確實存在的,我現在已經用了加密,已經不能夠繞過驗證了。第二個問題對於我的系統來說是不存在的,因為My Code中並沒有使用你說的那兩種擷取IP的方式,你無法欺騙我的系統。
總結了大家的觀點,我們主要做以下幾點討論:
- 採用Cookie記錄驗證碼是最方便的方式,無論是從開發成本還是從維護、運營成本來看,都是性價比最高的。在不至於太嚴格要求的網站中,建議採用Cookie的方式。
- 驗證碼如果需要存入Cookie中,需要加密。加密方式有很多,最普通的是md5。但是現在網上已有很多md5密碼資料庫(如 http://www.cmd5.com/),有的甚至提供API,所以單純只使用md5是靠不住的。在我的加密中,我將傳統產生md5的方式做了一些修改,基本能夠保證惡意訪問者無法通過加密的Cookie來擷取到真實驗證碼。
public static string GetMd5(string str) { string cl =DateTime.Now.Month+ str + DateTime.Now.Day;//將真實驗證碼加上首碼與尾碼後再加密; string pwd = ""; MD5 md5 = MD5.Create();//執行個體化一個md5對像 // 加密後是一個位元組類型的數組,這裡要注意編碼UTF8/Unicode等的選擇 byte[] s = md5.ComputeHash(Encoding.UTF8.GetBytes(cl)); s.Reverse(); //翻轉產生的MD5碼 // 通過使用迴圈,將位元組類型的數群組轉換為字串,此字串是常規字元格式設定化所得 for (int i = 3; i < s.Length-1; i++) //只取MD5碼的一部分;惡意訪問者無法知道我取的是哪幾位。 { // 將得到的字串使用十六進位類型格式。格式後的字元是小寫字母,如果使用大寫(X)則格式後的字元是大寫字元 pwd = pwd + (s[i]<198?s[i]+28:s[i]).ToString("X"); // 進一步對產生的MD5碼做一些改造。 } return pwd; }
- 限制頻繁訪問是一定要做的。
在我的網站中,正常訪問的使用者不可能在4小時內訪問200次以上。這是有統計來源的。根據我採用的一些統計代碼,我發現訪問最頻繁的使用者,在4小時內訪問的最大值僅為76次,而且這是一個最特殊的特例而已。
所以如果我一旦發現有使用者在4小時內訪問太多次數, 幾乎就可以判斷他為惡意使用者。
這不是一個最絕對的判斷方式,但仍然是可行性最高、成本最低的。
- 限制頻繁訪問的方式,使用Cache最好,使用XML最次。
在ASP.NET網站限制訪問頻率一文中,我提出了使用Cache來記錄使用者的IP、訪問方式、訪問次數。這也是參考了很多大型網站防止DoS攻擊的方式。
有朋友提出,使用Cache或許會造成伺服器資源開銷,建議使用XML;如果XML太大,可以分成零碎模組。
我的觀點是,XML檔案的效率確實太差。以前我測試過,十萬行資料的XML檔案,一次讀寫操作就接近1秒,更不用說網站的頻繁訪問、需要頻繁操作XML檔案了。然後同樣的十萬條Cache資料,佔用內容僅為幾十M(如一條資料佔用1k記憶體,十萬條佔用100M;然後實際操作中,1條資料遠沒有1k),處理速度在10毫秒內。
不僅如此,就算我們把訪問記錄到XML檔案中,我們對它進行讀寫操作,也是要將它載入記憶體的。而十萬行資料的XML檔案,與十萬行Cache中的KeyValue對,佔用的記憶體也是不能同日而語的。
綜上所述,使用XML檔案進行記錄,不僅不能夠減少伺服器壓力(記憶體、硬碟、CPU計算次數),反而還增加了伺服器壓力、大大增加了請求回應時間。最好的方式仍然是使用Cache。
暫時就這些吧。。希望大家繼續給點意見,也可以去我的網站(http://freesms.cloudapp.net/)試試,看你能不能夠找到漏洞進行破解 。o(∩_∩)o 非常感謝部落格園的朋友,跟你們交流我非常開心!