Logo

新人日誌

首頁關於我部落格

新人日誌

Logo

網站會不定期發佈技術筆記、職場心得相關的內容,歡迎關注本站!

網站
首頁關於我部落格
部落格
分類系列文

© 新人日誌. All rights reserved. 2020-present.

跨站請求偽造(CSRF)入門指南:攻擊原理、實例與防禦方法

最後更新:2025年3月4日架構

本文為 資安入門 系列文,第 7 篇

  1. OWASP Top 10:最新的 Web 安全風險與防範措施(2021 版)
  2. MD5 加密演算法是什麼?
  3. SHA-1 是什麼?為什麼不再安全?
  4. 深入解析 Session:從概念到運作方式
  5. 什麼是 Session Fixation(會話固定攻擊)?
  6. HTTP 與 HTTPS 的差別:新手完整指南
  7. 跨站請求偽造(CSRF)入門指南:攻擊原理、實例與防禦方法 👈所在位置
  8. 跨站指令碼攻擊(XSS)入門指南:從原理到防禦的全解析
  9. SQL 注入攻擊全解析:從入門到防禦實戰指南
  10. 新手指南:深入了解 Content-Security-Policy (CSP) 與網站安全
  11. 從零理解 Same-Origin Policy:瀏覽器安全的第一道防線
  12. 跨來源資源共享(CORS)完整指南:打破瀏覽器的安全邊界

在網路世界中,安全漏洞無處不在,而 跨站請求偽造(CSRF) 正是其中一種常見且危險的攻擊手法。

想像一下:當你登入銀行網站後,不小心點了一個不明連結,結果帳戶裡的錢竟被自動轉走——這就是 CSRF 攻擊的可怕之處。

本文將以 新手友善的視角,完整解析 CSRF 的運作原理、實際攻擊案例,以及開發者該如何防禦。

無論你是剛入門的工程師,還是對資安有興趣的學習者,都能透過這篇文章建立清晰的觀念。


什麼是跨站請求偽造(CSRF)?

CSRF(Cross-Site Request Forgery)是一種利用「用戶已登入的合法身分」發動攻擊的手法。

攻擊者誘導使用者在 不知情的情況下,透過瀏覽器向目標網站發送偽造的請求(例如轉帳、修改密碼),進而執行惡意操作。

以生活情境比喻,假設你有一張「銀行 VIP 會員卡」,只要出示卡片就能辦理業務。

攻擊者偷偷複製了你的卡片(盜用瀏覽器 Cookie),並偽造一張「轉帳申請單」讓你簽名(誘導點擊惡意連結)。

由於銀行只認卡片不認人,攻擊者便成功利用你的身分完成轉帳。


CSRF 攻擊如何運作?

具體流程

1. 用戶登入信任網站,瀏覽器儲存「身分通行證」

  • 當用戶登入 example-bank.com 時,伺服器會發送 Session Cookie 給瀏覽器。
  • Cookie 儲存機制:
    • Cookie 由瀏覽器保存在用戶的電腦中(如 Chrome 的 Cookies 資料庫)。
    • 每個 Cookie 嚴格綁定「域名」,例如 example-bank.com 的 Cookie 不會與 evil-site.com 共用。
  • 此時狀態:
    用戶如同獲得「銀行 VIP 卡」,後續操作瀏覽器會自動出示此卡驗證身分。

2. 用戶誤入惡意網站,跨分頁的 Cookie 危機

  • 用戶可能在另一個分頁或視窗開啟惡意連結(例如釣魚郵件中的 evil-site.com)。
  • 關鍵行為:
    • 瀏覽器會 持續保留所有網站的 Cookie,除非手動清除或 Cookie 過期。
    • 即使切換分頁,example-bank.com 的 Cookie 仍存在瀏覽器中。
      → 這正是 CSRF 攻擊的核心漏洞!

3. 惡意網站發動「隱形攻擊指令」

  • 攻擊者在 evil-site.com 頁面中暗藏以下程式碼:
  <!-- 偽裝成圖片載入,實際發送轉帳請求 -->
  <img src="https://example-bank.com/transfer?amount=10000&to=ATTACKER" 
       style="display:none">

或使用自動提交的表單:

  <body onload="document.forms[0].submit()">
    <form action="https://example-bank.com/transfer" method="POST">
      <input type="hidden" name="amount" value="10000">
      <input type="hidden" name="to_account" value="ATTACKER_ACCOUNT">
    </form>
  </body>

4. 瀏覽器「自動帶 Cookie」的雙面刃

  • 同源政策(Same-Origin Policy)的盲點:
    • 瀏覽器禁止 evil-site.com 讀取 example-bank.com 的 Cookie。
    • 但允許 evil-site.com 發送請求 到 example-bank.com,並自動附加該域名的 Cookie!
      → 請求看似來自已登入用戶,伺服器難以辨別真偽。
  • 攻擊請求的組成:
  POST /transfer HTTP/1.1
  Host: example-bank.com
  Cookie: session_id=abc123   # 瀏覽器自動附加!
  Content-Type: application/x-www-form-urlencoded

  amount=10000&to_account=ATTACKER_ACCOUNT

5. 伺服器的致命誤判

  • 伺服器檢查 Cookie 有效 → 認為是合法用戶的操作。
  • 未經驗證直接執行轉帳指令,攻擊成功!

攻擊成功的三大必要條件

條件技術細節範例情境
1. 用戶已登入且 Cookie 有效瀏覽器儲存的 Session Cookie 未過期,且未設定 SameSite 防護屬性用戶登入銀行後未登出,直接瀏覽其他網站
2. 目標網站缺乏 CSRF 防護未使用 CSRF Token、未驗證 Referer、未設定 SameSite Cookie銀行允許純 Cookie 驗證請求,表單未嵌入隨機 Token
3. 惡意請求可構造API 路徑與參數格式可預測(如固定 URL + 簡單參數)銀行使用 POST /transfer?amount=100&to=123 這樣無防護的 API 設計
技術細節瀏覽器儲存的 Session Cookie 未過期,且未設定 SameSite 防護屬性
範例情境用戶登入銀行後未登出,直接瀏覽其他網站
技術細節未使用 CSRF Token、未驗證 Referer、未設定 SameSite Cookie
範例情境銀行允許純 Cookie 驗證請求,表單未嵌入隨機 Token
技術細節API 路徑與參數格式可預測(如固定 URL + 簡單參數)
範例情境銀行使用 POST /transfer?amount=100&to=123 這樣無防護的 API 設計

為什麼 Cookie 機制會成為幫兇?技術深度解析

瀏覽器的「自動化便利」 vs 「安全風險」

  • 設計初衷:
    Cookie 是為了讓用戶免於重複登入(例如保持購物車狀態),卻被攻擊者反向利用。
  • 跨站請求的矛盾:
  • 瀏覽器的自動化便利性,導致跨站請求「帶著合法身分」闖關成功。

Same-Origin Policy 的不足

  • 僅限制「讀取」跨站資料,卻允許「發送」跨站請求。
    → 攻擊者不需要竊取 Cookie,只需「借用」瀏覽器自動帶上的 Cookie。

實例演練:一個簡單的 CSRF 攻擊

情境設定

假設某銀行提供以下轉帳 API:

POST /transfer
參數:
- amount=1000       # 轉帳金額
- to_account=12345  # 目標帳戶

正常操作流程

用戶在銀行網站手動填寫表單,送出轉帳請求:

<!-- 合法表單 -->
<form action="https://example-bank.com/transfer" method="POST">
  <input type="text" name="amount" value="1000">
  <input type="text" name="to_account" value="12345">
  <button>確認轉帳</button>
</form>

攻擊者構造的惡意頁面

攻擊者建立一個看似無害的頁面,內藏自動提交的表單:

<!-- 惡意頁面 -->
<body onload="document.forms[0].submit()">
  <form action="https://example-bank.com/transfer" method="POST">
    <input type="hidden" name="amount" value="10000">
    <input type="hidden" name="to_account" value="ATTACKER_ACCOUNT">
  </form>
</body>

當已登入銀行的用戶訪問此頁面時,瀏覽器會自動發送轉帳請求,完成攻擊!


如何防禦 CSRF 攻擊?

CSRF Token 驗證

▶ 原理:伺服器生成隨機 Token 嵌入表單,提交時驗證是否匹配。

▶ 實作範例:

<!-- 表單中嵌入 Token -->
<form action="/transfer" method="POST">
  <input type="hidden" name="csrf_token" value="RANDOM_STRING">
  <!-- 其他表單欄位 -->
</form>
# 伺服器端驗證
if request.form['csrf_token'] != session['csrf_token']:
    return "Invalid CSRF Token", 403

CSRF Token 的設計核心

CSRF Token 是一種 由伺服器生成的隨機加密字串,其防禦效果依賴以下關鍵特性:

特性技術原理對抗 CSRF 攻擊的作用
隨機性每次表單生成時動態產生(如 UUID v4、加密亂數)攻擊者無法預測或構造有效 Token
與 Session 綁定Token 儲存在伺服器的 Session 中,與當前用戶綁定確保 Token 僅對特定用戶有效
單次使用部分實作中,Token 提交後立即失效(可選策略)防止重放攻擊(Replay Attack)
同源限制Token 只能由合法網站的前端程式碼讀取(遵守同源政策)攻擊者無法從跨站頁面竊取 Token
技術原理每次表單生成時動態產生(如 UUID v4、加密亂數)
對抗 CSRF 攻擊的作用攻擊者無法預測或構造有效 Token
技術原理Token 儲存在伺服器的 Session 中,與當前用戶綁定
對抗 CSRF 攻擊的作用確保 Token 僅對特定用戶有效
技術原理部分實作中,Token 提交後立即失效(可選策略)
對抗 CSRF 攻擊的作用防止重放攻擊(Replay Attack)
技術原理Token 只能由合法網站的前端程式碼讀取(遵守同源政策)
對抗 CSRF 攻擊的作用攻擊者無法從跨站頁面竊取 Token

攻擊者為什麼無法取得 Token?

情境模擬:攻擊者構造惡意表單

假設攻擊者嘗試在 evil-site.com 建立以下表單:

<!-- 惡意頁面 -->
<form action="https://example-bank.com/transfer" method="POST">
  <input type="hidden" name="amount" value="10000">
  <input type="hidden" name="to_account" value="ATTACKER">
  <!-- 攻擊者猜測或偽造 Token -->
  <input type="hidden" name="csrf_token" value="FAKE_TOKEN"> 
</form>
關鍵限制:瀏覽器的同源政策(Same-Origin Policy)
  1. 攻擊者無法讀取合法網站的 Token
    • 即使使用者已登入 example-bank.com,evil-site.com 的前端 JavaScript 無法跨域讀取 合法網站的 DOM 內容(包含 Token)。
    • 例:若 Token 嵌入在 <input type="hidden" name="csrf_token" value="abc123">,攻擊者無法透過 JS 取得此值。
  1. Token 不存在於 Cookie 中
    • 伺服器將 Token 儲存在 Session 而非 Cookie,因此瀏覽器 不會自動攜帶 Token 在請求中。

CSRF Token 設計哲學

  1. 隨機性:Token 必須足夠亂數,無法被暴力破解或預測。
  2. 與用戶綁定:透過 Session 確保 Token 專屬於當前用戶。
  3. 同源隔離:依賴瀏覽器同源政策,防止跨站竊取 Token。

「CSRF Token 是伺服器給用戶的一個動態密碼,攻擊者既看不到也猜不到,因此無法偽造合法請求。」

SameSite Cookie 屬性

▶ 原理:限制 Cookie 僅在相同網站(Same Site)的請求中傳送。

▶ 設定方法(HTTP Response Header):

Set-Cookie: session_id=abc123; SameSite=Strict
  • Strict:完全禁止跨站請求帶 Cookie(適用敏感操作)
  • Lax:允許部分安全跨站請求(例如導航到目標網站)

驗證請求來源(Referer Header)

▶ 原理:檢查 HTTP 請求的 Referer 標頭是否來自合法域名。

▶ 注意:某些瀏覽器可能不發送 Referer,且攻擊者可偽造此值(需搭配其他機制)。

Referer 是什麼?用現實比喻快速理解

什麼是 Referer Header?
  • 技術定義:
    HTTP 請求中的 Referer(註:拼寫錯誤是歷史遺留問題,正確應為 Referrer)標頭,代表「這個請求是從哪個網頁連結過來的」。

    例如:當你點擊 news-site.com 上的連結進入 shop.com,shop.com 的伺服器會看到:
  GET /product/123 HTTP/1.1
  Host: shop.com
  Referer: https://news-site.com/article/456
  • 比喻理解:
    Referer 就像「快遞包裹上的寄件人地址」。
    伺服器(收件人)可以透過地址(Referer)知道包裹(請求)是從哪裡寄來的。

為什麼檢查 Referer 能防禦 CSRF?

正常操作 vs CSRF 攻擊的 Referer 差異
  • 合法操作情境:
    用戶在 example-bank.com 的轉帳頁面提交表單 → Referer 是 https://example-bank.com/transfer。
  • CSRF 攻擊情境:
    用戶在 evil-site.com 被誘導發送轉帳請求 → Referer 是 https://evil-site.com/fake-page。

防禦原理

伺服器檢查 Referer 是否來自「自己家的域名」,如果不是就拒絕請求。
例如:

# 伺服器端檢查 Referer 的偽代碼
def process_request(request):
    referer = request.headers.get('Referer')
    if not referer.startswith('https://example-bank.com'):
        return "Request blocked: Invalid Referer", 403
    # 繼續處理請求...

為什麼不能單獨依賴 Referer 檢查?

瀏覽器可能不發送 Referer
  • 隱私設定影響:
    某些瀏覽器(如 Firefox 嚴格模式、Brave)或插件(如防追蹤工具)會屏蔽 Referer。
  • 從 HTTPS 到 HTTP 的請求:
    安全政策規定,若當前頁面是 HTTPS,而請求目標是 HTTP,瀏覽器 不會發送 Referer。

案例模擬:

用戶在 https://example-bank.com 登入後,從 http://evil-site.com 觸發 CSRF 攻擊:
→ 請求的 Referer 被屏蔽 → 伺服器誤判合法請求!

攻擊者可偽造 Referer(特定條件下)
  • 透過中間攻擊手法:
    如果網站存在 開放重定向(Open Redirect)漏洞,攻擊者可構造看似合法的 Referer。
    例如:
  Referer: https://example-bank.com/redirect?url=evil-site.com
  • 利用瀏覽器特性:
    某些舊版瀏覽器允許透過 meta 標籤或 JavaScript 修改 Referer,但現代瀏覽器已修復此問題。
跨域子域名的混淆風險
  • 錯誤配置案例:
    若伺服器允許所有子域名(如 *.example-bank.com),攻擊者可能註冊 evil.example-bank.com 發動攻擊。
    → Referer 檢查通過,但實際是跨站請求!

實務建議:如何安全使用 Referer 檢查?

僅作為「補充防禦」
  • 絕對不要單獨依賴 Referer,需搭配以下任一機制:
    • CSRF Token
    • SameSite Cookie
    • 自定義請求標頭(如 X-Requested-With)
嚴格驗證邏輯
  • 檢查 Referer 的 協議(HTTP/HTTPS)、完整域名、端口。
  • 拒絕空 Referer 或非預期來源。

其他防禦手段

  • 雙重提交 Cookie:將 Token 同時存在 Cookie 和表單,伺服器比對兩者。
  • 自定義 Header:要求 AJAX 請求包含特定 Header(例如 X-Requested-With)。
  • 敏感操作二次驗證:例如要求重新輸入密碼或簡訊驗證碼。

總結與最佳實踐

CSRF 攻擊的關鍵在於 濫用瀏覽器的自動帶 Cookie 機制,而防禦的核心是「確保請求來自合法來源」。

開發者應至少實作以下措施:

  1. 為所有敏感操作啟用 CSRF Token。
  2. 為 Session Cookie 設定 SameSite 屬性。
  3. 定期更新框架與函式庫(如 Django、Spring Security 已內建 CSRF 防護)。

資安沒有銀彈,唯有持續學習與多層次防護,才能打造更安全的網路環境!

目前還沒有留言,成為第一個留言的人吧!

發表留言

留言將在審核後顯示。

架構

目錄

  • 什麼是跨站請求偽造(CSRF)?
  • CSRF 攻擊如何運作?
  • 具體流程
  • 攻擊成功的三大必要條件
  • 為什麼 Cookie 機制會成為幫兇?技術深度解析
  • 實例演練:一個簡單的 CSRF 攻擊
  • 情境設定
  • 正常操作流程
  • 攻擊者構造的惡意頁面
  • 如何防禦 CSRF 攻擊?
  • CSRF Token 驗證
  • CSRF Token 設計哲學
  • SameSite Cookie 屬性
  • 驗證請求來源(Referer Header)
  • 防禦原理
  • 其他防禦手段
  • 總結與最佳實踐