1. 程式人生 > >網頁驗證碼的基本原理、常見漏洞及解決方法

網頁驗證碼的基本原理、常見漏洞及解決方法

    前些天查了一些驗證碼的資料,瞭解了一些資訊,也發現了一些網站確實存在的漏洞。下文將分析驗證碼原理及存在的問題。首先宣告:本文僅僅探討技術,請各位讀者不要利用這些資訊進行非法行為,筆者不承擔任何連帶責任!當然,筆者能力有限,這裡也提供不了什麼實質性技術,只是將自己獲取的一些資訊與大家分享,呵呵。
    驗證碼的原理其實比較簡單,一般都是鏈到一個動態頁面,然後後臺伺服器生成一個隨機數,利用這個隨機數對映一張圖片,最後將這張圖片返回客戶,同時將這個隨機數儲存起來,當用戶提交驗證碼時檢測填寫的驗證碼是否和這個隨機數相同。這裡我想重點說三點,這三點處理不好都可能被破解者利用。一是隨機數的生成,二是隨機數和圖片的對映,三是隨機數如何儲存。
    隨機數的生成是第一個需要注意的問題。大部分網站採用的都是偽隨機數生成演算法,而目前的偽隨機數生成演算法種類不多,編寫驗證碼程式碼的人如果演算法功底不強(或者偷懶),往往都採用後臺語言類庫所提供的偽隨機數生成演算法,這樣從演算法的角度入手破解的可能性還是比較大的。但是由於破解者往往數學功底也一般所以被破解的可能性也有限,但是一旦被破解驗證碼也就形同虛設。筆者演算法功底也一般,在此不做深入研究,建議採用優良的隨機數生成演算法。
    隨機數和圖片的對映問題,我所瞭解的有兩種。一種是將所有驗證碼影象以二進位制形式儲存在資料庫(或檔案系統)中,實現時根據生成的隨機數將對應的圖片取出即可;第二種是根據隨機數實時的生成一張圖片,然後返回(當然,為了提高效率會加入伺服器端快取策略)。第一種方式比較健壯,因為可以在圖片上加上很多噪音,第二種方式就比較危險,主要看你生成圖片的演算法如何了,如果不好的話很容易被破解。這裡的典型破解方式是利用影象識別技術分析顯示的圖片。如果圖片是通過第二種方式生成的就很容易被識別出來,現在手機上的手寫技術就是一個典型的例子。但是如果採用第一種,預先在每張圖片中加入大量噪音,識別率還是很小的。
    隨機數的儲存問題看似簡單,其實是最容易被破解者利用的。很明顯,隨機數是與會話密切相關的,以.NET為例,儲存方式無外乎有三種:一種是採用Cookie,將驗證碼加密(可以採用優良的加密演算法在後臺完成)然後寫入客戶端Cookie中;第二種是Session,直接將隨機數儲存到某個會話變數上;第三種是Application,將隨機數儲存到全域性變數中。由於這個問題比較脆弱,也很容易別利用,下面重點分析。
    儲存在Cookie中其實是很危險的一種做法。雖然可以在後臺將隨機值加密後再儲存到Cookie中,但是卻為破解者進行重放攻擊提供了一條途徑。比如說驗證碼是1234,使用者通過看圖片肯定知道是1234,此時Cookie雖然沒有直接儲存1234,但卻儲存了1234對應的密文,而這個密文是直接可以獲取的。這樣使用者就知道驗證碼1234對應的密文是什麼。如果下次再出現這個密文就可以立即知道對應的密碼是1234。這樣只要破解者有足夠的耐性就完全可以進行重放攻擊。
    對於.NET來說,儲存在Application中和Session中類似。如果儲存在Application中就需要採用某個標識來區分不同的會話,這個標識當然是非SessionId莫屬了。Session的實現原理這裡就不多說了,.NET允許將Session資料儲存在伺服器端和SQL SERVER資料庫中,對於SessionId的儲存可以在Cookie中,也可以設定成Cookieless通過虛擬目錄解決。對ASP來說,漏洞要多很多,首先頁面和程式碼是混合的,如果獲取了後臺的讀許可權就可以知道所有細節了,另外它的SessionId不支援Cookieless,只能儲存到Cookie中。如果一個驗證碼是通過ASP實現的,那破解者完全可以通過ASP自身的問題破解。這裡側重分析各類實現均存在的通用問題。這樣,後臺的驗證流程是:會話開始->生成回話編號[可能儲存在客戶端]->生成隨機數->獲取隨機數所對映的驗證碼圖片->儲存隨機數[儲存在伺服器端,利用回話編號和變數名訪問]->客戶端顯示驗證圖片->使用者填寫驗證碼->資料提交到後臺[含會話編號]->後臺根據回話編號和變數名取出儲存的隨機數->驗證是否正確。
    一間事務所經過的環節越多,出現問題的可能性就越大。這個驗證流程中可被破解的地方理論上也很多,但是破解這個流程的難度等同於破解Session機制。當然,這個破解Session機制可能是直接的[難度相當大],也可能是間接的,[如非法訪問Web伺服器,非法訪問Session儲存資料庫等]。然而還有一個更容易破解也很容易解決的問題。這個驗證流程雖然已經比較長了,但其實還不完整。由於HTTP一次迴應只能是文字或者圖片等二進位制資料,不能同時包含,這樣驗證碼圖片的獲取和操作頁面的獲取就必然是兩次HTTP請求。也就是說請求操作頁面和請求驗證碼圖片的操作不是原子的。這樣,如果使用者第一完整的請求了操作頁面和驗證碼圖片,以後就只請求宿主頁面不再請求驗證碼圖片,這樣驗證碼就永遠維持在第一次顯示的驗證碼了。這樣就為一些含驗證碼網頁的暴力破解提供了一種可能。
    就總結到這了。從中至少可以看出——網頁驗證碼的設計還是需要仔細斟酌的,如果設計不好,還是很容易出現瑕疵的,呵呵。