在瞭解 CSRF 以前咱們須要科普兩個前提。首先是登陸權限驗證的方式有不少種,目前絕大多數網站採用的仍是 session 會話任務的方式。session 機制簡單的來講就是服務端使用一個鍵值對記錄登陸信息,同時在 cookie 中將 session id(即剛纔說的鍵)存儲到 cookie 中。另外咱們又知道瀏覽器中 HTTP(s) 請求是會自動幫咱們把 cookie 帶上傳給服務端的。這樣在每次請求的時候經過 cookie 獲取 session id,而後經過它在服務端獲取登陸信息便可完成用戶權限的校驗。php
原本這也是個不錯的功能。可是因爲 cookie 實在是太開放了,若是一個用戶在 A 網站登陸了,若是用戶在 B 網站訪問的時候發送了一個 A 網站的請求,那麼這個請求實際上是帶有這個用戶在 A 網站的登陸信息的。若是這時候 B 站的 A 網站請求是用戶不知道的,那就是很是嚴重的危害了。以上的過程就是跨站請求攻擊,即 Cross-Site Request Forgery,即 CSRF。html
簡單總結 CSRF 漏洞就是利用網站權限校驗方面的漏洞在用戶不知覺的狀況下發送請求,達到「假裝」用戶的目的。攻擊者利用 CSRF 實現的攻擊主要有如下幾種:前端
其中 CSRF 蠕蟲如其名所指就是產生蠕蟲效果,會將 CSRF 攻擊一傳十,十傳百。如:某社區私信好友的接口和獲取好友列表的接口都存在CSRF漏洞,攻擊者就能夠將其組合成一個CSRF蠕蟲——當一個用戶訪問惡意頁面後經過CSRF獲取其好友列表信息,而後再利用私信好友的CSRF漏洞給其每一個好友發送一條指向惡意頁面的信息,只要有人查看這個信息裏的連接,CSRF蠕蟲就會不斷傳播下去,其可能形成的危害和影響很是巨大!web
從上文的描述中咱們能夠知道 CSRF 有兩個特色:利用 cookie 自動攜帶的特性以及跨站攻擊。那麼針對這兩個特性可使用以下解決方法。瀏覽器
你們都知道 HTTP 頭中有一個 Referer 字段,這個字段用以標明請求來源於哪一個地址。經過在網站中校驗請求的該字段,咱們能知道請求是不是從本站發出的。咱們能夠拒絕一切非本站發出的請求,這樣避免了 CSRF 的跨站特性。cookie
const { parse } = require('url');
module.exports = class extends think.Logic {
indexAction() {
const referrer = this.ctx.referrer();
const {host: referrerHost} = parse(referrer);
if(referrerHost !== 'xxx') {
return this.fail('REFERRER_ERROR');
}
}
}
複製代碼
一樣以 ThinkJS 爲例,只要在 Logic 中簡單判斷下便可。這種方式利用了客戶端沒法構造 Referrer 的特性,雖然簡單,不過當網站域名有多個,或者常常變換域名的時候會變得很是的麻煩,同時也具備必定的侷限性。session
因爲 CSRF 是利用了瀏覽器自動傳遞 cookie 的特性,另一個防護思路就是校驗信息不經過 cookie 傳遞,在其餘參數中增長隨機加密串進行校驗。這裏又有兩種辦法:post
除了上面說到的 cookie 登陸問題形成的 CSRF 攻擊,還有就是增刪改等操做使用 GET 請求完成,當該請求未校驗登陸信息的時候也容易形成 CSRF 攻擊。固然這種就比較低級了,不過也仍是須要注意。特別是當下 SPA 的流行,愈來愈多的 AJAX 請求,咱們更是要注意 CSRF 攻擊的可能。網站
參考資料:ui