Web安全漏洞之CSRF

ThinkJS發表於2019-03-04

什麼是 CSRF

在瞭解 CSRF 之前我們需要科普兩個前提。首先是登入許可權驗證的方式有很多種,目前絕大多數網站採用的還是 session 會話任務的方式。session 機制簡單的來說就是服務端使用一個鍵值對記錄登入資訊,同時在 cookie 中將 session id(即剛才說的鍵)儲存到 cookie 中。另外我們又知道瀏覽器中 HTTP(s) 請求是會自動幫我們把 cookie 帶上傳給服務端的。這樣在每次請求的時候通過 cookie 獲取 session id,然後通過它在服務端獲取登入資訊即可完成使用者許可權的校驗。

本來這也是個不錯的功能。但是由於 cookie 實在是太開放了,如果一個使用者在 A 網站登入了,如果使用者在 B 網站訪問的時候傳送了一個 A 網站的請求,那麼這個請求其實是帶有這個使用者在 A 網站的登入資訊的。如果這時候 B 站的 A 網站請求是使用者不知道的,那就是非常嚴重的危害了。以上的過程就是跨站請求攻擊,即 Cross-Site Request Forgery,即 CSRF。

CSRF 的危害

簡單總結 CSRF 漏洞就是利用網站許可權校驗方面的漏洞在使用者不知覺的情況下傳送請求,達到“偽裝”使用者的目的。攻擊者利用 CSRF 實現的攻擊主要有以下幾種:

  1. 攻擊者能夠欺騙受害使用者完成該受害者所允許的任一狀態改變的操作,比如:更新賬號細節,完成購物,登出甚至登入等操作
  2. 獲取使用者的隱私資料
  3. 配合其他漏洞攻擊
  4. CSRF 蠕蟲

其中 CSRF 蠕蟲如其名所指就是產生蠕蟲效果,會將 CSRF 攻擊一傳十,十傳百。如:某社群私信好友的介面和獲取好友列表的介面都存在CSRF漏洞,攻擊者就可以將其組合成一個CSRF蠕蟲——當一個使用者訪問惡意頁面後通過CSRF獲取其好友列表資訊,然後再利用私信好友的CSRF漏洞給其每個好友傳送一條指向惡意頁面的資訊,只要有人檢視這個資訊裡的連結,CSRF蠕蟲就會不斷傳播下去,其可能造成的危害和影響非常巨大!

防禦方法

從上文的描述中我們可以知道 CSRF 有兩個特點:利用 cookie 自動攜帶的特性以及跨站攻擊。那麼針對這兩個特性可以使用如下解決方法。

檢查 Referer 欄位

大家都知道 HTTP 頭中有一個 Referer 欄位,這個欄位用以標明請求來源於哪個地址。通過在網站中校驗請求的該欄位,我們能知道請求是否是從本站發出的。我們可以拒絕一切非本站發出的請求,這樣避免了 CSRF 的跨站特性。

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 的特性,雖然簡單,不過當網站域名有多個,或者經常變換域名的時候會變得非常的麻煩,同時也具有一定的侷限性。

Token 驗證

由於 CSRF 是利用了瀏覽器自動傳遞 cookie 的特性,另外一個防禦思路就是校驗資訊不通過 cookie 傳遞,在其他引數中增加隨機加密串進行校驗。這裡又有兩種辦法:

  1. 隨機字串:為每一個提交增加一個隨機串引數,該引數服務端通過頁面下發,每次請求的時候補充到提交引數中,服務端通過校驗該引數是否一致來判斷是否是使用者請求。由於 CSRF 攻擊中攻擊者是無從事先得知該隨機字串的值,所以服務端就可以通過校驗該值拒絕可以請求。
  2. JWT:實際上除了 session 登入之外,現在越來越流行 JWT token 登入校驗。該方式是在前端記錄登入 token,每次請求的時候通過在 Header 中新增認證頭的方式來實現登入校驗過程。由於 CSRF 攻擊中攻擊者無法知道該 token 值,通過這種方式也是可以防止 CSRF 攻擊的。關於如何在 ThinkJS 中使用 JWT 的話可以參考之前的文章《ThinkJS JWT 鑑權實踐》。當然 token 登入方式除了 JWT 之外還有 OAuth 等很多種方式。

後記

除了上面說到的 cookie 登入問題造成的 CSRF 攻擊,還有就是增刪改等操作使用 GET 請求完成,當該請求未校驗登入資訊的時候也容易造成 CSRF 攻擊。當然這種就比較低階了,不過也還是需要注意。特別是當下 SPA 的流行,越來越多的 AJAX 請求,我們更是要注意 CSRF 攻擊的可能。

參考資料:

相關文章