深入理解 CSRF
提供對跨網站請求偽造(CSRF)攻擊的深入探討,解釋其機制,示範示例,並詳述各種預防方法以增強網絡應用程式的安全性。
當進行網頁開發時,尤其涉及 Cookie,我們經常會聽到類似 "這個設定有助於防止 CSRF" 的說法。然而,很多人對於 "CSRF" 的真正含義只有模糊的概念。
今天,我們將深入探討 CSRF(跨網站請求偽造),這是一個常見的網絡安全漏洞。這將有助於我們更有效地處理 CSRF 相關問題。
什麼是 CSRF?
CSRF(跨網站請求偽造)是一種網絡攻擊,攻擊者誘使已經認證的用戶執行非預期操作。簡單來說,就是 "黑客假裝成用戶以執行未經授權的操作"。
CSRF 如何運作
要瞭解 CSRF,我們需要掌握幾個關鍵概念:
瀏覽器的同源政策
同源政策是瀏覽器中的一項安全功能,限制來自一個來源的文件或腳本如何與另一個來源的資源互動。
一個來源由協議(如 HTTP 或 HTTPS)、域名和端口號組成。例如,https://example.com:443
是一個來源,而 https://demo.com:80
是另一個。
同源政策限制不同來源頁面之間的數據訪問,這意味著:
- 一個來源的 JavaScript 無法讀取另一個來源的 DOM
- 一個來源的 JavaScript 無法讀取另一個來源的 Cookie、IndexedDB 或 localStorage
- 一個來源的 JavaScript 無法向另一個來源發送 AJAX 請求(除非使用 CORS)
然而,為了保持 Web 的開放性和互操作性(如從 CDNs 加載資源或向第三方 APIs 發送請求 進行日誌記錄),同源政策不限制跨來源的網絡請求:
- 頁面可以向任何來源發送 GET 或 POST 請求(如加載圖片或提交表單)
- 可以包含來自任何來源的資源(如
<script>
、<img>
、<link>
、<iframe>
標籤)
自動 Cookie 發送機制
自動 Cookie 發送機制是瀏覽器的一項重要功能。當瀏覽器向一個域發送請求時,它會自動附上該域的所有 Cookie。這個過程是自動的,不需要任何 JavaScript 代碼或用戶交互。
這一機制可以讓網站輕鬆地記住用戶的登入狀態,因為每個請求自動攜帶用戶身份信息。
加粗
例如,當你登入一個銀行網站(bank.com
)並獲取身份 Cookie,然後當你點擊查看你的對帳單時,瀏覽器會自動找到所有匹配 bank.com
的 Cookie 並將它們附加到對帳單請求。銀行的伺服器隨後可以從後台識別你並返回你的對帳單信息。
CSRF 攻擊步驟
-
用戶登入目標網站(如銀行網站),獲得身份驗證 Cookie。 這一步使用自動 Cookie 發送機制。當銀行網站設置身份驗證 Cookie 後,瀏覽器將自動將此 Cookie 附加到發送給該網站的每個請求中。
-
在不登出的情況下,用戶訪問了惡意網站。 此時,由於同源政策,惡意網站無法直接讀取或修改銀行網站的 Cookie。這保護了用戶的身份信息不被直接竊取。
-
惡意網站包含了一個發向目標網站的請求(如轉賬操作)。 雖然同源政策限制跨來源訪問,但它允許跨來源網絡請求,如通過
<img>
、<form>
標籤發起的請求。攻擊者利用了這個 "漏洞"。 -
用戶的瀏覽器自動發送這一請求,並附上目標網站的 Cookie。 這是 CSRF 攻擊的核心。它利用了同源政策允許跨來源請求和自動 Cookie 發送機制(即使由惡意網站觸發的請求也會攜帶匹配域的 Cookie)。
-
目標網站接收到請求,驗證 Cookie 有效後執行操作。 伺服器無法判斷請求是否來自合法用戶操作,因為附加的 Cookie 是有效的。
CSRF 攻擊示例
讓我們用一個具體的例子來說明 CSRF 攻擊是如何發生的。我們將使用一個虛構的銀行網站 bank.com
作為示例。
首先,用戶訪問 https://bank.com
並登入他們的帳戶。
成功登入後,伺服器設置了一個身份驗證 Cookie,例如:
用戶在銀行網站上進行轉賬操作,比如轉賬 1000 美元給 Alice。這一操作可能發送如下請求:
現在,假設攻擊者創建了一個包含以下 HTML 的惡意網站 https://evil.com
:
當用戶在未登出銀行帳戶的情況下點擊 https://evil.com
的鏈接,因為他們已經登入 bank.com
,瀏覽器擁有一個有效的 session_id
Cookie。
惡意頁面加載後,會自動提交隱藏的表單,向 https://bank.com/transfer
發送轉賬請求。
用戶的瀏覽器自動將 bank.com
Cookie 附加到此請求。bank.com
伺服器接收到請求,驗證 Cookie 有效後執行了這一未經授權的轉賬操作。
常見的 CSRF 攻擊防範方法
以下是幾種常用的 CSRF 防禦方法。我們將詳細解釋每一種方法的原理及其如何有效防止 CSRF 攻擊:
使用 CSRF 令牌
CSRF 令牌是抵御 CSRF 攻擊最常見且有效的方法之一。其工作原理如下:
- 伺服器為每個會話生成唯一且不可預測的令牌。
- 此令牌嵌入到所有敏感操作的表單中。
- 當用戶提交表單時,伺服器驗證令牌的有效性。
因為 CSRF 令牌是一個綁定到用戶會話的唯一值,攻擊者無法知道或猜測這個值(因為每個會話不同),即使攻擊者誘使用戶發送請求,伺服器也會因為缺少有效的 CSRF 令牌而拒絕該請求。
實施例子:
在伺服器端(使用 Node.js 和 Express):
在前端 JavaScript:
檢查 Referer
標頭
Referer
標頭包含發起請求的頁面的 URL。通過檢查 Referer
標頭,伺服器可以確定請求是否來自合法來源。
由於 CSRF 攻擊通常來自不同的域名,Referer
標頭將顯示攻擊者的域名。通過驗證 Referer
是否為預期值,可以封鎖來自未知來源的請求。
然而,值得注意的是,這種方法並不完全可靠,因為某些瀏覽器可能不會發送 Referer 標頭,用戶也可以通過瀏覽器設置或插件禁用 Referer 標頭。
實施例子:
使用 SameSite
Cookie 屬性
SameSite
是用於控制 Cookie 是否與跨站點請求一起發送的 Cookie 屬性。它有三個可能的值:
Strict
: Cookie 僅在同一站點的請求中發送。Lax
: Cookie 在同一站點的請求和頂級導航中發送。None
: Cookie 在所有跨站點請求中發送(必須與Secure
屬性一起使用)。
當 SameSite
設置為 Strict
時,可以完全防止第三方網站發送 Cookie,從而有效防範 CSRF 攻擊。
如果 SameSite
設置為 Lax
,則在允許一些常見的跨站使用情況(如從外部鏈接進入網站)的同時,保護敏感操作。
實施例子:
使用自定義請求標頭
對於 AJAX 請求,可以添加自定義請求標頭。由於同源政策的限制,攻擊者無法在跨站請求中設置自定義標頭。伺服器可以檢查這一自定義標頭的存在性來驗證請求的合法性。
實施例子:
在前端:
在伺服器端:
雙重 Cookie 驗證
雙重 Cookie 驗證是有效的 CSRF 防禦技術。其核心原理是伺服器生成一個隨機令牌,將其設置為 Cookie 並將其嵌入頁面(通常是作為隱藏表單字段)。當瀏覽器發送請求時,它自動包含該 Cookie,而頁面的 JavaScript 將該令牌作為請求 參數發送。然後伺服器驗證 Cookie 中的令牌與請求參數中的令牌是否匹配。
雖然攻擊者可以在跨站請求中包含目標網站的 Cookie,但他們無法讀取或修改 Cookie 的值,也無法訪問或修改頁面中的令牌值。要求請求同時包含來自 Cookie 和參數的令牌,確保請求來自有權限讀取 Cookie 的來源,從而有效防禦 CSRF 攻擊。
對敏感操作使用重新驗證
對於特別敏感的操作(如更改密碼或進行大額轉賬),可以要求用戶重新驗證。 這為用戶提供了一個額外的安全檢查點。即使用戶成功發起了 CSRF 攻擊,也無法通過重新驗證步驟。
實施建議:
- 在執行敏感操作之前,重定向到單獨的身份驗證頁面。
- 在此頁面上,要求用戶輸入密碼或其他身份驗證信息。
- 驗證通過後,生成一次性令牌並在後續敏感操作中使用該令牌。
總結
通過這次深入討論,我們希望你現在對 CSRF 攻擊有了更全面的理解。 我們不僅了解了 CSRF 如何運作,還探討了各種有效的防禦措施。所有這些方法都可以有效增強網絡應用程式的安全性。
希望這些知識可以幫助你在日常開發中更好地處理 CSRF 相關問題,並建立更安全的網絡應用程式。