[Http] 跨站請求偽造(CSRF)

Himmelbleu發表於2024-10-07

基本概念

當一個使用者已經登入並且在當前域名下儲存了相關的 Cookie(如身份驗證資訊等),如果開啟一個偽造的 HTML 頁面,並且該頁面中的 <form> 元素的 action 屬性包含完整的 API 請求全路徑指向同一域名,瀏覽器在傳送該表單請求時會自動攜帶該域名下儲存的 Cookie

同一域名下的所有請求(包括表單提交、XHR、Fetch 請求等)都會自動附帶瀏覽器中儲存的 Cookie 資訊,除非使用了 SameSite、HttpOnly 等安全設定來限制特定的 Cookie 行為。

攻擊過程

  1. 使用者登入可信站點:使用者登入一個網站後,網站通常會在使用者瀏覽器中設定一個認證 cookie,用於維持使用者的會話。
  2. 攻擊者偽造請求:攻擊者建立一個惡意網頁(或者一段惡意程式碼),該頁面向使用者已登入的網站傳送請求。這些請求可能是透過 <form> 表單提交、圖片連結、AJAX 請求等方式偽造的。
  3. 瀏覽器自動攜帶 cookie:由於請求的目標域名與使用者登入的網站相同,瀏覽器會自動附帶之前的認證 cookie(如 session cookie),伺服器將其視為合法使用者的請求。
  4. 伺服器執行請求:如果網站沒有足夠的防護措施,伺服器會執行該請求,認為這是由合法使用者發出的,從而造成惡意操作,比如更改賬戶資訊、進行轉賬等。

假設一個使用者登入了銀行網站 bank.com,並且銀行網站在使用者的瀏覽器中設定了認證 Cookie。攻擊者傳送給使用者一個包含以下內容的惡意 HTML 頁面:

<form action="https://bank.com/transfer" method="POST">
    <input type="hidden" name="to_account" value="attacker_account">
    <input type="hidden" name="amount" value="1000">
    <input type="submit" value="Submit">
</form>

使用者一旦開啟這個頁面,表單會自動提交,並攜帶瀏覽器中的認證 Cookie。銀行網站接收到請求後,認為這是使用者自願的轉賬操作,從而執行了轉賬。

防禦 CSRF

  1. CSRF Token: 在表單中加入一個唯一的 Token(令牌),伺服器在接收到請求時驗證這個 Token 是否與使用者會話中的一致。由於攻擊者無法獲取合法的 Token,因此偽造的請求會被拒絕。
  2. SameSite Cookie: 將 Cookie 的 SameSite 屬性設定為 LaxStrict,限制 Cookie 在跨站請求中的傳遞。這樣,攻擊者無法在跨站請求中利用使用者的 Cookie。
  3. 檢查 Referer 和 Origin 頭: 伺服器端可以檢查請求的 RefererOrigin 頭,確保請求是來自同一站點,而不是第三方站點。

相關文章