一.CSRF是什麼?javascript
CSRF(Cross-site request forgery),中文名稱:跨站請求僞造,也被稱爲:one click attack/session riding,縮寫爲:CSRF/XSRF。php
二.CSRF能夠作什麼?html
你這能夠這麼理解CSRF攻擊:攻擊者盜用了你的身份,以你的名義發送惡意請求。CSRF可以作的事情包括:以你名義發送郵件,發消息,盜取你的帳號,甚至於購買商品,虛擬貨幣轉帳......形成的問題包括:我的隱私泄露以及財產安全。java
三.CSRF漏洞現狀瀏覽器
CSRF這種攻擊方式在2000年已經被國外的安全人員提出,但在國內,直到06年纔開始被關注,08年,國內外的多個大型社區和交互網站分別 爆出CSRF漏洞,如:NYTimes.com(紐約時報)、Metafilter(一個大型的BLOG網站),YouTube和百度HI......而 如今,互聯網上的許多站點仍對此毫無防備,以致於安全業界稱CSRF爲「沉睡的巨人」。安全
四.CSRF的原理服務器
下圖簡單闡述了CSRF攻擊的思想:session
從上圖能夠看出,要完成一次CSRF攻擊,受害者必須依次完成兩個步驟:工具
1.登陸受信任網站A,並在本地生成Cookie。網站
2.在不登出A的狀況下,訪問危險網站B。
看到這裏,你也許會說:「若是我不知足以上兩個條件中的一個,我就不會受到CSRF的攻擊」。是的,確實如此,但你不能保證如下狀況不會發生:
1.你不能保證你登陸了一個網站後,再也不打開一個tab頁面並訪問另外的網站。
2.你不能保證你關閉瀏覽器了後,你本地的Cookie馬上過時,你上次的會話已經結束。(事實上,關閉瀏覽器不能結束一個會話,但大多數人都會錯誤的認爲關閉瀏覽器就等於退出登陸/結束會話了......)
3.上圖中所謂的攻擊網站,多是一個存在其餘漏洞的可信任的常常被人訪問的網站。
上面大概地講了一下CSRF攻擊的思想,下面我將用幾個例子詳細說說具體的CSRF攻擊,這裏我以一個銀行轉帳的操做做爲例子(僅僅是例子,真實的銀行網站沒這麼傻:>)
示例1:
銀行網站A,它以GET請求來完成銀行轉帳的操做,如:http://www.mybank.com/Transfer.php?toBankId=11&money=1000
危險網站B,它裏面有一段HTML的代碼以下:
首先,你登陸了銀行網站A,而後訪問危險網站B,噢,這時你會發現你的銀行帳戶少了1000塊......
爲何會這樣呢?緣由是銀行網站A違反了HTTP規範,使用GET請求更新資源。在訪問危險網站B的以前,你已經登陸了銀行網站A,而B中 的<img>以GET的方式請求第三方資源(這裏的第三方就是指銀行網站了,本來這是一個合法的請求,但這裏被不法分子利用了),因此你的瀏 覽器會帶上你的銀行網站A的Cookie發出Get請求,去獲取資源「http://www.mybank.com /Transfer.php?toBankId=11&money=1000」,結果銀行網站服務器收到請求後,認爲這是一個更新資源操做(轉帳 操做),因此就馬上進行轉帳操做......
示例2:
爲了杜絕上面的問題,銀行決定改用POST請求完成轉帳操做。
銀行網站A的WEB表單以下:
後臺處理頁面Transfer.php以下:
危險網站B,仍然只是包含那句HTML代碼:
和示例1中的操做同樣,你首先登陸了銀行網站A,而後訪問危險網站B,結果.....和示例1同樣,你再次沒了1000塊~T_T,此次事故的 緣由是:銀行後臺使用了$_REQUEST去獲取請求的數據,而$_REQUEST既能夠獲取GET請求的數據,也能夠獲取POST請求的數據,這就形成 了在後臺處理程序沒法區分這究竟是GET請求的數據仍是POST請求的數據。在PHP中,可使用$_GET和$_POST分別獲取GET請求和POST 請求的數據。在JAVA中,用於獲取請求數據request同樣存在不能區分GET請求數據和POST數據的問題。
示例3:
通過前面2個慘痛的教訓,銀行決定把獲取請求數據的方法也改了,改用$_POST,只獲取POST請求的數據,後臺處理頁面Transfer.php代碼以下:
然而,危險網站B與時俱進,它改了一下代碼:
若是用戶還是繼續上面的操做,很不幸,結果將會是再次不見1000塊......由於這裏危險網站B暗地裏發送了POST請求到銀行!
總結一下上面3個例子,CSRF主要的攻擊模式基本上是以上的3種,其中以第1,2種最爲嚴重,由於觸發條件很簡單,一 個<img>就能夠了,而第3種比較麻煩,須要使用JavaScript,因此使用的機會會比前面的少不少,但不管是哪一種狀況,只要觸發了 CSRF攻擊,後果都有可能很嚴重。
理解上面的3種攻擊模式,其實能夠看出,CSRF攻擊是源於WEB的隱式身份驗證機制!WEB的身份驗證機制雖然能夠保證一個請求是來自於某個用戶的瀏覽器,但卻沒法保證該請求是用戶批准發送的!
CSRF工具的防護手段
1. 儘可能使用POST,限制GET
GET接口太容易被拿來作CSRF攻擊,看第一個示例就知道,只要構造一個img標籤,而img標籤又是不能過濾的數據。接口最好限制爲POST使用,GET則無效,下降攻擊風險。
固然POST並非萬無一失,攻擊者只要構造一個form就能夠,但須要在第三方頁面作,這樣就增長暴露的可能性。
2. 瀏覽器Cookie策略
IE六、七、八、Safari會默認攔截第三方本地Cookie(Third-party Cookie)的發送。可是Firefox二、三、Opera、Chrome、Android等不會攔截,因此經過瀏覽器Cookie策略來防護CSRF攻擊不靠譜,只能說是下降了風險。
PS:Cookie分爲兩種,Session Cookie(在瀏覽器關閉後,就會失效,保存到內存裏),Third-party Cookie(即只有到了Exprie時間後纔會失效的Cookie,這種Cookie會保存到本地)。
PS:另外若是網站返回HTTP頭包含P3P Header,那麼將容許瀏覽器發送第三方Cookie。
3. 加驗證碼
驗證碼,強制用戶必須與應用進行交互,才能完成最終請求。在一般狀況下,驗證碼能很好遏制CSRF攻擊。可是出於用戶體驗考慮,網站不能給全部的操做都加上驗證碼。所以驗證碼只能做爲一種輔助手段,不能做爲主要解決方案。
4. Referer Check
Referer Check在Web最多見的應用就是「防止圖片盜鏈」。同理,Referer Check也能夠被用於檢查請求是否來自合法的「源」(Referer值是不是指定頁面,或者網站的域),若是都不是,那麼就很可能是CSRF攻擊。
可是由於服務器並非何時都能取到Referer,因此也沒法做爲CSRF防護的主要手段。可是用Referer Check來監控CSRF攻擊的發生,卻是一種可行的方法。
5. Anti CSRF Token
如今業界對CSRF的防護,一致的作法是使用一個Token(Anti CSRF Token)。
例子:
1. 用戶訪問某個表單頁面。
2. 服務端生成一個Token,放在用戶的Session中,或者瀏覽器的Cookie中。
3. 在頁面表單附帶上Token參數。
4. 用戶提交請求後, 服務端驗證表單中的Token是否與用戶Session(或Cookies)中的Token一致,一致爲合法請求,不是則非法請求。
這個Token的值必須是隨機的,不可預測的。因爲Token的存在,攻擊者沒法再構造一個帶有合法Token的請求實施CSRF攻擊。另外使用Token時應注意Token的保密性,儘可能把敏感操做由GET改成POST,以form或AJAX形式提交,避免Token泄露。
注意:
CSRF的Token僅僅用於對抗CSRF攻擊。當網站同時存在XSS漏洞時候,那這個方案也是空談。因此XSS帶來的問題,應該使用XSS的防護方案予以解決。