簡介
CSRF(Cross Site Request Forgery),也就是跨站域請求偽造,也可以縮寫為XSRF,是一種對網站的惡意利用。雖然看起來跟XSS有點相像,但是兩者基本是完全不同的。XSS利用的是站點內的信任用戶,而CSRF則通過偽裝成來自受信任用戶的請求來利用受信任的網站。CSRF往往認為比XSS更具危險性和難以防范。
CSRF攻擊能夠盜用身份,以我們的名義發送惡意請求,發送郵件,發消息,盜取賬號,購買商品,虛擬貨幣轉賬等。
CSRF攻擊原理
上圖較為全面形象展示了CSRF攻擊的整個過程。在上圖中,A網站
通過cookie來識別用戶C
,當用成功進行身份驗證之后瀏覽器就會得到一個標識其身份的cookie,只要不關閉或者退出其登錄,訪問A網站
都會帶上這個cookie。如果在這個時候,用戶C
訪問了被黑客控制的網站B
,網站B
又發出要求訪問網站A
的請求,然后就會由用戶C
端根據網站B
發起的請求,帶着A網站
的cookie訪問網站A
,但這並不是用戶C
的本意,那么這就是所謂的請求偽造了,跨站是因為這是由B端發起的。而且這是受害者用戶C完全不知情的請求,從而在未授權的情況下完成權限保護下的操作。
舉例子:
比如說,受害者Bob在銀行有一筆存款,通過對銀行的網站發起請求http://bank.example/withdraw?account=bob&amount=1000000&for=bob2
將1000000的存款轉到bob2賬戶。通常情況下,該請求發送到網站后,服務器會先驗證該請求是否來自一個合法的session,並且該session的用戶Bob時已經成功登陸的,所以這個請求是會被響應的。
恰巧在此時,黑客Mr.Hack知道了Bob身懷巨款,而自己在銀行中也有一個賬戶hack,於是打起了壞心思,他知道上面那個url會進行轉賬操作。Mr.Hack可以自己發送一個請求,http://bank.example/withdraw?account=bob&amount=1000000&for=hack
,但是雖然已經發送端銀行服務器端了,但是服務器並不會響應,因為經過服務器驗證,這個請求是沒有合法cookie,服務器知道這並不是Bob用戶發來的請求。
這時,Mr.Hack靈機一動,想到了使用CSRF的攻擊方式,他自己先做了一個網站,在網站中放入如下代碼,這屬於前端代碼中標簽的內容src="http://bank.example/withdraw?account=bob&amount=1000000&for=hack"
,然后Mr.Hack會使用渾身解數來引誘受害人Bob訪問網站,比如廣告或者一些頗具誘惑性的網頁等。當受害人Bob訪問該網站時,經過事件觸發,受害者Bob自己的瀏覽器端就會發起上訴url中的請求,並且會附帶Bob瀏覽器中的cookie。在大多數情況下,bank服務器端會拒絕該請求,因為服務器端並沒有最近的cookie信息。但是Bob不巧在最近訪問了該銀行站點,他的瀏覽器中的cookie尚未過期,也就是與銀行網站之間的seesion尚未過期的話,那就糟了。上面那個請求url就會得到相應,銀行就真的將100000轉到hack賬戶上了,而且受害人Bob目前還完全不知情。
注意事項
黑客能拿到cookie嗎
事實上,使用csrf攻擊,黑客一般是不會拿到cookie的,也看不到cookie的內容。CSRF攻擊是借助受害者的合法cookie騙取服務器的信任。
黑客使用CSRF攻擊實際主要是為了以受害者的身份執行所描述的命令,這一特點也正好是CSRF與XSS的區別所在,XSS是利用script文件相惡意服務器發送請求但這些請求是包含入侵方想要知曉的信息的,其主要目的是為了獲取信息,竊取服務器中的數據,包括cookie。
什么樣的請求是要CSRF保護的
我們要保護的是那些可以直接改變數據的服務,而那些只能讀取數據的服務則不需要CSRF的保護。通常而言,GET請求作為請求數據的請求而不會去修改數據,所以某些框架(如Spring Security)里防護CSRF的filter限定的method是POST/PUT/DELETE等,而沒有限定GET。
比如上面那個例子中轉賬的請求會直接改變賬戶的金額,一般為POST的請求,需要保護。而查詢余額是對金額的讀取操作,不改變數據,CSRF攻擊就無法利用了。
CSRF防御的常規思路
驗證HTTP Referer字段
眾所周知,在HTTP頭中有個字段的名字叫Referer,它記錄了該HTTP請求的來源地址。在通常情況下,訪問一個安全受限頁面的請求其referer需要來自同一個網站,比如需要訪問http://bank.example/withdraw?account=bob&amount=1000000&for=hack
,用戶需要先登陸到bank.example,然后通過頁面的轉賬按鈕來觸發轉賬事件。這時,該請求的referer值就是按鈕所在的那個頁面的url。但是如果黑客要實施CSRF攻擊的話,referer的值就會是Mr.Hack自己所搭建的那個網站的url,而一經銀行的服務器驗證是站外請求,就會直接拒絕,從而防御CSRF攻擊。
在請求地址中添加token並驗證
CSRF能夠成功完全是因為黑客能夠偽造用戶的請求,在該請求中所有的用戶驗證信息都存在於cookie中,因此黑客才可以利用cookie來通過安全驗證。要抵御CSRF,關鍵在於在請求中放入黑客不能偽造的信息,並且該信息不存在在cookie中。那么我們就可以在HTTP請求中以參數的形式加入一個隨機生成的token,並在服務器端建立一個攔截器來驗證這個token,如果請求中沒有token或token的內容的不正確,則認為不安全從而直接拒絕該請求。(一般是服務器端生成的)
具體內容可看下面這篇博客:CSRF攻擊預防的Token生成以及驗證原理 - 簡書 (jianshu.com)
使用token的一個難點就是如何把token以參數的形式加入請求。
在HTTP頭中自定義屬性並驗證
這里也是使用token並進行驗證,和上一種方法不同的是,這里並不是把token以參數的形式置於HTTP請求中去,而是把它放到HTTP投中自定義的屬性里。
參考文章