天天看點

再論驗證碼安全:請及時銷毀你的驗證碼

為了友善大家了解,這裡我就以一個投票的應用網站為例進行說明。投票網站首先要防止的就是使用者不斷點選投票按鈕來重複投票;當然,避免重複投票的解決辦法有很多,比如記錄IP、寫入Session、Cookie甚至還有要求使用者輸入身份證号碼等。但是你記錄IP,那我就寫一個程式來模拟發包,每投1票後自動換代理,然後繼續投票,如果是寫入到Session中那麼我寫個投票程式,每投1票就重新開啟一個新的會話就是。如果是記入Cookie,那我該表Cookie的值再模拟投票發包,要輸入身份證号進行驗證?寫個身份證号碼生成程式也十分容易……

在投票機器人面前,記錄IP、記錄身份證号碼、寫入Session和Cookie等防作弊技術形同虛設。是以在投票網站中驗證碼功能必不可少。那麼我們将驗證碼功能加入到網站投票中:

1.生成驗證碼圖檔的頁面CreateImg.aspx,其背景代碼為:

再論驗證碼安全:請及時銷毀你的驗證碼

protected void Page_Load(object sender, EventArgs e)

再論驗證碼安全:請及時銷毀你的驗證碼

   {

再論驗證碼安全:請及時銷毀你的驗證碼

string checkCode = CreateCode(4);//生成随機是4位驗證碼

再論驗證碼安全:請及時銷毀你的驗證碼

       Session["CheckCode"] = checkCode;//将驗證碼儲存到Session中

再論驗證碼安全:請及時銷毀你的驗證碼

       CreateImage(checkCode);//将驗證碼以圖檔的方式輸出

再論驗證碼安全:請及時銷毀你的驗證碼

   }  

2.在使用者單擊投票按鈕後觸發的事件:

再論驗證碼安全:請及時銷毀你的驗證碼

protected void btnVote_Click(object sender, ImageClickEventArgs e)

再論驗證碼安全:請及時銷毀你的驗證碼

{

再論驗證碼安全:請及時銷毀你的驗證碼

    if (!ValidateUserInfo())//驗證IP在資料庫中的情況,一個IP一天隻能投5張票,進而防止重複投票

再論驗證碼安全:請及時銷毀你的驗證碼

    {

再論驗證碼安全:請及時銷毀你的驗證碼

        UIHelper.Alert(Page, "一個IP一天隻能投5張票,請勿重複投票");

再論驗證碼安全:請及時銷毀你的驗證碼

        return;

再論驗證碼安全:請及時銷毀你的驗證碼

    }

再論驗證碼安全:請及時銷毀你的驗證碼

    if (Session["CheckCode"] == null)

再論驗證碼安全:請及時銷毀你的驗證碼
再論驗證碼安全:請及時銷毀你的驗證碼

        UIHelper.Alert(Page, "驗證碼已過期,請重新輸入");

再論驗證碼安全:請及時銷毀你的驗證碼
再論驗證碼安全:請及時銷毀你的驗證碼
再論驗證碼安全:請及時銷毀你的驗證碼

    if (Session["CheckCode"].ToString().ToLower() != txbCode.Text.ToLower())//驗證碼忽略大小寫

再論驗證碼安全:請及時銷毀你的驗證碼
再論驗證碼安全:請及時銷毀你的驗證碼

        UIHelper.Alert(Page, "驗證碼錯誤");

再論驗證碼安全:請及時銷毀你的驗證碼
再論驗證碼安全:請及時銷毀你的驗證碼
再論驗證碼安全:請及時銷毀你的驗證碼

    else//驗證碼正确

再論驗證碼安全:請及時銷毀你的驗證碼
再論驗證碼安全:請及時銷毀你的驗證碼

        UpdateVote();//修改資料庫,将投票數加1

再論驗證碼安全:請及時銷毀你的驗證碼
再論驗證碼安全:請及時銷毀你的驗證碼

OK,大功告成!這個程式邏輯上有問題嗎?沒有吧,驗證碼是生成的圖檔,圖檔是有幹擾因素的,不會被程式識别,而且驗證碼的内容是儲存到伺服器的,邏輯處理也是錯。似乎一切都那麼完美,但是事實并不是這樣,對于這樣的投票網站,我的投票機器人仍然肆無忌憚的不斷切換IP,不斷刷票。(要做投票機器人的同志們注意啦,不要看到投票的地方是有驗證碼的就一籌莫展了哦,也許他的網站就存在以下描述的漏洞哦!)

漏洞就出在投票時對驗證碼進行驗證後沒有對伺服器上Session中的驗證碼内容進行銷毀。在平時使用IE浏覽時,每投票一次後重新整理頁面,驗證碼生成頁面被重新請求,是以Session值在請求驗證碼生成頁時被替換,是以不會有什麼問題。但是現在面對的是投票機器人,我的機器人在第一次請求時獲得驗證碼的圖檔并展示給使用者,使用者肉眼識别驗證碼,然後輸入程式的文本框中,由于伺服器上驗證碼的内容并沒有被銷毀,而且投票程式也不會再請求驗證碼生成圖檔的URL,是以接下來每次使用相同的SessionID和使用者輸入的驗證碼值,伺服器驗證投票時  

if (Session["CheckCode"].ToString().ToLower() != txbCode.Text.ToLower())

都會傳回false,驗證碼都是通過的,是以投票自然成功。終究是百密一疏啊!費盡心思防止投票作弊,最終卻因為這一個地方的疏忽而前功盡棄,投票作弊成功,投票結果還是被投票機器人所左右。

也許有人想到了,那可以在Session中放置一個标記,如果投票成功了就将标記置“1”,下次請求時判斷Session中标記為“1”就拒絕投票就是了。但是投票隻是我這裡舉的一個例子,像論壇這種用驗證碼防止使用者惡意灌水的總不可能限制使用者隻發一帖吧。論壇發帖時的驗證碼如果沒有被及時銷毀,那麼我的灌水機器人就仍然可以到處肆意發帖了,哈哈哈哈。

要避免這個漏洞被利用還是很簡單,隻需要将上面的代碼中投票完成後立即将驗證碼從伺服器上銷毀即可:

再論驗證碼安全:請及時銷毀你的驗證碼
再論驗證碼安全:請及時銷毀你的驗證碼
再論驗證碼安全:請及時銷毀你的驗證碼
再論驗證碼安全:請及時銷毀你的驗證碼
再論驗證碼安全:請及時銷毀你的驗證碼
再論驗證碼安全:請及時銷毀你的驗證碼
再論驗證碼安全:請及時銷毀你的驗證碼
再論驗證碼安全:請及時銷毀你的驗證碼
再論驗證碼安全:請及時銷毀你的驗證碼
再論驗證碼安全:請及時銷毀你的驗證碼
再論驗證碼安全:請及時銷毀你的驗證碼
再論驗證碼安全:請及時銷毀你的驗證碼
再論驗證碼安全:請及時銷毀你的驗證碼
再論驗證碼安全:請及時銷毀你的驗證碼
再論驗證碼安全:請及時銷毀你的驗證碼
再論驗證碼安全:請及時銷毀你的驗證碼
再論驗證碼安全:請及時銷毀你的驗證碼
再論驗證碼安全:請及時銷毀你的驗證碼
再論驗證碼安全:請及時銷毀你的驗證碼
再論驗證碼安全:請及時銷毀你的驗證碼
再論驗證碼安全:請及時銷毀你的驗證碼
再論驗證碼安全:請及時銷毀你的驗證碼
再論驗證碼安全:請及時銷毀你的驗證碼

Session["CheckCode"] = null;//驗證碼使用後馬上從伺服器銷毀

再論驗證碼安全:請及時銷毀你的驗證碼

}

這樣如果仍然使用相同的SessionID和驗證碼值,那麼将會在 if (Session["CheckCode"] == null)這裡判斷出驗證碼已經過期,想成功投票?重新請求驗證碼頁面獲得驗證碼圖檔,然後重新輸入驗證碼吧!

這個問題雖然看起來不以為然,但是正所謂“千裡之堤毀于蟻穴”,隻要驗證碼沒有從伺服器上銷毀,那麼頁面上的驗證碼還是形同虛設,和驗證碼的圖檔位址為<img src="CreateCheckCode.aspx?code=af5d" alt="驗證碼">

這樣把驗證碼直接暴露在HTML中或者直接使用文本而不是圖檔來表示驗證碼有什麼差別呢?

另外有人提到,這裡是Session儲存驗證碼才會有這個問題,那完全基于Cookie加密的呢?在前面的文章中我也提到過Cookie加密的方式儲存驗證碼的内容,但是今天我又仔細想了一下,得出結論:驗證碼内容不能儲存到用戶端,也就是說根本就不應該使用Cookie加密的方式,Cookie加密儲存驗證碼明文是沒有什麼意義的,必須要在伺服器端儲存與驗證碼相關的資訊(比如驗證碼明文或者驗證碼加密解密密鑰)。為什麼不能使用Cookie加密儲存驗證碼?我舉個簡單的例子吧:

比如現在頁面上顯示的驗證碼是1234,同時抓包發現送出的時候Cookie中有值:“EncryptCode=asdf”這是驗證碼的明文經過加密後的密文,我不知道加密算法是什麼,但是我每次程式送出時就将1234作為驗證碼的值同時将“EncryptCode=asdf”作為Cookie的一部分發送到伺服器,那麼伺服器将1234加密後與發送過來的Cookie值“asdf”一比較,二者相同,驗證通過!!!

是以我認為驗證碼的明文是不可能完全基于用戶端的,必須要在伺服器上儲存與驗證碼相關的資訊(驗證碼明文或密鑰)。既然要在伺服器上儲存相關資訊,那麼就可能出現這個漏洞。當然這是我想遍了所有驗證碼明文儲存的方法後得出的結論,我還不敢拍胸脯說這是100%正确的,如果大家認為這個結論不正确,那希望能夠提出具體的情況。

希望大家若做過驗證碼的都再回頭看看自己的驗證碼内容在伺服器上及時銷毀沒有。這個錯誤很容易犯,我在某大公司的網站上都發現了這個漏洞,可見犯此錯的網站絕對不在少數。

最後希望大家的網站更加安全,更加健壯。

本文轉自深藍居部落格園部落格,原文連結:http://www.cnblogs.com/studyzy/archive/2008/06/04/1213192.html,如需轉載請自行聯系原作者