Cross-Site Request Forgery (CSRF)

👀 4 min read 👀

大家好,我是 Cindy,發現自己最近記憶力真的不好,以前看過的東西還是不記得,最近嚴重到 3 天前的事情也忘光,所以想盡可能做紀錄,於是這篇文章就誕生了QQ

又過了一陣子發現這文章沒寫完,而且還有點混亂 XDD,趁過年的時候做了個整理,這篇文章最大的目的是如果我又忘記了可以直接翻來看,如果我有寫錯也歡迎大家留言告訴我唷。

什麼是 Cross Site

Cross Site 中文是跨網站,講完(誒!),如何被說成是跨網站,目前我覺得是如果在同源政策中被定義的非同源網站,在非同源網站之間做資源存取,應該就可以被稱為 cross site。

Same-origin policy

同源政策是指在 Web 瀏覽器中,允許某個網頁腳本訪問另一個網頁的數據,但前提是這兩個網頁必須有相同的 URI、主機名和埠號,一旦兩個網站滿足上述條件,這兩個網站就被認定為具有相同來源。即同源政策限制了程式碼和不同網域資源間的互動。

同源政策僅適用於指令碼,這意味著某網站可以通過相應的 HTML 標籤存取不同來源網站上的圖像、CSS 和動態載入指令碼等資源。而跨站請求偽造就是利用同源政策不適用於 HTML 標籤的缺陷。

推薦大家看這個 youtube 講了一下關於 The Same Origin Policy 的歷史,從 Windows 95 出發 XDDD。

什麼是 Cross-Site Request Forgery (CSRF)

Cross-Site Request Forgery 簡稱 CSRF,中文叫做跨站請求偽造,也被稱為 one-click attack 或者 session riding,通常縮寫為 CSRF 或者 XSRF, 是一種利用使用者在當前已登入的 Web 應用程式上執行非本意操作的攻擊方法。跟跨站腳本攻擊(XSS)相比,XSS 利用的是使用者對指定網站的信任,CSRF 利用的是網站對使用者網頁瀏覽器的信任。

CSRF Introduction and what is the Same-Origin Policy? - web 0x04 這個影片做了一段簡單的說明和示範

What is a CSRF? | OWASP Top 10 2013 | Video by Detectify 這個影片示範了一次 CSRF 的攻擊

Rails 的 CSRF 對策

most Rails applications use cookie-based sessions. Either they store the session ID in the cookie and have a server-side session hash, or the entire session hash is on the client-side. In either case the browser will automatically send along the cookie on every request to a domain, if it can find a cookie for that domain. The controversial point is that if the request comes from a site of a different domain, it will also send the cookie.

By default, Rails includes an unobtrusive scripting adapter, which adds a header called X-CSRF-Token with the security token on every non-GET Ajax call. Without this header, non-GET Ajax requests won’t be accepted by Rails. When using another library to make Ajax calls, it is necessary to add the security token as a default header for Ajax calls in your library. To get the token, have a look at tag printed by <%= csrf_meta_tags %> in your application view.

Rails 預設是 cookie-based sessions 的,關於 CSRF 的攻擊,Rails 也用一套解法 => CSRF token。
CSRF token 保護的重點在於,由於每次請求都會發送 cookie session_id(或帶有 JWT 的 cookie),因此我們需要一個額外的訊息(CSRF token),服務器將確認為用戶的瀏覽器操作,而不是惡意鏈接。

為什麼 rails api mode 預設沒有處理 CSRF token

Rails 文件中提到: APIs may want to disable this behavior since they are typically designed to be state-less: that is, the request API client handles the session instead of Rails.

前後端分離的 CSRF token

當前後端完全分離的時候,由於前端不是 Rails 渲染的,我們就不能直接用 csrf_meta_tags Rails 魔法

Rails CSRF protection for SPA 這篇文章詳細說明了各種實作方式,其中一種方式 通過身份驗證標頭使用 JWT 令牌的 SPA 提供給我們另一個觀點,就是如果不用 cookie 作身份驗證其實就不會有 CSRF 的問題,但要注意的是僅僅沒有 CSRF 問題,並不意味著跨站腳本攻擊 (XSS) 無法竊取 token!當後端 API 只接受 header(不接受 cookie)時,前端 SPA 會面臨更大的安全壓力。

參考資料