CSRF(Cross-site request forgery)跨站請求僞造:攻擊者誘導受害者進入第三方網站,在第三方網站中,向被攻擊網站發送請求。利用受害者在被攻擊網站已經獲取的註冊憑證,繞事後臺的用戶驗證,達到冒充用戶對被攻擊網站執行某項操做的目的。html
一個典型的CSRF攻擊流程:前端
例如:算法
用戶A瀏覽Gmail郵件,因好奇點擊了一封「甩賣比特幣,只要998」的廣告郵件。打開後一片空白,隨後用戶A關閉了頁面。但此時CSRF攻擊已經完成,用戶A的Gmail郵件將逐一轉發到黑客的郵箱。具體是怎麼發生的呢,關鍵在於那個空白頁面的源碼:後端
<form method="POST" action="https://mail.google.com/mail/h/ewt1jmuj4ddv/?v=prf" enctype="multipart/form-data">
<input type="hidden" name="cf2_emc" value="true"/>
<input type="hidden" name="cf2_email" value="hacker@hakermail.com"/>
.....
<input type="hidden" name="irf" value="on"/>
<input type="hidden" name="nvp_bu_cftb" value="Create Filter"/>
</form>
<script>
document.forms[0].submit();
</script>複製代碼
這個頁面只要一打開就會向Gmail發送一個post請求。請求中,執行了‘Create Filter’命令(自動轉發郵件),將全部郵件轉發到黑客郵箱hacker@hakermail.com。因爲A剛登錄了Gmail,用戶登陸憑證被保存在cookie中,因此這個空白頁發出的post請求就攜帶了登錄證實,因而成功給用戶A配置了過濾器。黑客能夠查看全部用戶A的郵件,包括一些敏感信息:郵箱驗證碼等等。此事件原型是2007年Gmail的CSRF漏洞:www.davidairey.com/google-Gmai…。目前此漏洞已修復。api
GET類型攻擊:http請求時,敏感參數跟在url後面,攻擊者很容易獲取併發送包含受害者信息的跨域請求。跨域
POST類型攻擊:如上案列所示。瀏覽器
連接類型攻擊:頁面中注入惡意連接,誘導用戶點擊跳轉。安全
據上所示,CSRF一般是由第三方網站發起,所以能夠經過加強自身網站的安全性來防護:bash
同源檢測服務器
同源策略上分爲兩部分:一是http請求接口的同源,還有一個是cookie的domain屬性的同源。
1. http請求,可使用origin header、referer header肯定來源域名。
在部分請求中,請求的header中會攜帶origin字段,表明請求的域名;也有不存在origin的狀況,IE11對同源的定義有別於其餘瀏覽器,還有一個就是302重定向以後origin不包含在重定向的請求中,由於重定向請求是定向到新的服務器,避免泄露origin信息。
http請求header中還有另一個記錄該請求來源地址的屬性referer。referer值是由瀏覽器提供的,不可排除瀏覽器自身安全性問題,和部分狀況下攻擊者隱藏甚至篡改本身請求的referer。在同源策略下,能夠把referer屬性設置成same-origin,對於同源的額連接和引用會發送referer,對於跨域則不攜帶referer。
設置referer的三種方法:在csp設置;頁面頭部增設meta標籤;a標籤增長referer屬性
<a href="https://www.baidu.com/" ref="noreferrer">跳到百度</a>複製代碼
可是,在如下狀況下referer沒有或者不可信:
2. 在瀏覽器種下cookie時,若明確cookie的domain屬性(一級域名或是子域名),即僅在domain指定的域下的接口才會自動攜帶cookie,能夠解決部分跨域問題,但仍不能避免攻擊者僞造的域名和網站同域(本地服務器proxy代理請求時)。還能夠設置cookie爲Httponly,這樣cookie只能在請求中被攜帶,沒法用document.cooke讀取、修改。
token驗證
這裏的token驗證也有兩種,一種是CSRF token的加解密校驗,還有一個是雙重Cookie驗證。
1. CSRF token
用戶打開頁面時,服務器會個每一個用戶生成惟一的token,這個token是通過精密算法對數據進行加密,通常包括隨機字符串和時間戳。token會存在服務器的session中。頁面提交的請求都會攜帶這個token,當服務器拿到token後用相應解密算法獲得時間戳、及加密字符串,再和服務器session中存儲的token信息做比較來判斷該請求的有效性,這類token通常是隨機字符串。
分佈式校驗
在大型網站中,使用session存儲token會帶來很大壓力。訪問單臺服務器session是同一個。可是如今的大型網站中,咱們的服務器一般不止一臺,多是幾十臺甚至幾百臺之多,甚至多個機房均可能在不一樣的省份,用戶發起的HTTP請求一般要通過像Ngnix之類的負載均衡器以後,再路由到具體的服務器上,因爲Session默認存儲在單機服務器內存中,所以在分佈式環境下同一個用戶發送的屢次HTTP請求可能會前後落到不一樣的服務器上,致使後面發起的HTTP請求沒法拿到以前的HTTP請求存儲在服務器中的Session數據,從而使得Session機制在分佈式環境下失效,所以在分佈式集羣中CSRF Token須要存儲在Redis之類的公共存儲空間。
目前的解決辦法就是採用Encrypted Token Pattern方式,計算出一個結果,而不是隨機字符串。這樣就無需將token存儲在session中,只須要在拿到token的時候再計算一次就行。
Token是一個比較有效的CSRF防禦方法,只要頁面沒有XSS漏洞泄露Token,那麼接口的CSRF攻擊就沒法成功。其次,驗證碼和密碼其實也有CSRF token的做用。
2. 雙重Cookie驗證
雙重Cookie採用如下流程:
csrfcookie=v8g9e4ksfhw
)。POST https://www.a.com/comment?csrfcookie=v8g9e4ksfhw
)。此方法相對於CSRF Token就簡單了許多。能夠直接經過先後端攔截的的方法自動化實現。後端校驗也更加方便,只需進行請求中字段的對比,而不須要再進行查詢和存儲Token。
固然,此方法並無大規模應用,其在大型網站上的安全性仍是沒有CSRF Token高,緣由咱們舉例進行說明。
因爲任何跨域都會致使前端沒法獲取Cookie中的字段(包括子域名之間),因而發生了以下狀況:
www.a.com
,然後端的api域名爲api.a.com
。那麼在www.a.com
下,前端拿不到api.a.com
的Cookie,也就沒法完成雙重Cookie認證。a.com
下,這樣每一個子域均可以訪問。a.com
下的Cookie。upload.a.com
)。雖然這個子域下並無什麼值得竊取的信息。但攻擊者修改了a.com
下的Cookie。www.a.com
下,發起CSRF攻擊。