什麼是 CSRF 攻擊?如何防範?

2023年2月9日

💎 加入 E+ 成長計畫 與超過 250+ 位軟體工程師一起在社群中成長,並且獲得更深入、系統性軟體工程內容

《什麼是 XSS 攻擊?如何防範?》這篇文章中,我們討論到什麼是 XSS 以及防禦方法,在這篇文章我們會繼續討論另一種常見的網路攻擊方式 - 跨站請求偽造 Cross Site Request Forgery (CSRF)。

什麼是 CSRF 攻擊?

CSRF 是指跨站的請求偽造,這種攻擊方法會強迫使用者在他們已經驗證身份的網站中,執行某些惡意的偽造操作,因為已經驗證過該使用者,所以網站就會以操作來自該使用者,因此接受了該操作。舉例來說,某個使用者登入銀行帳戶後,去逛別的網站,但不小心點開惡意網站,該惡意網站中的程式碼用這名使用者的名義,進行未經同意的轉帳操作。

CSRF 之所以成立,是因為使用者的身份已經先被驗證過。如果要白話一點理解,就像是別人偷拿你的會員點數卡去買東西。但因為店家認卡,所以當看到小偷拿著你的卡,就相信小偷是你本人,於是接受該小偷使用你的點數進行消費。

CSRF 攻擊流程

  1. 使用者成功登入 A 銀行網站的帳戶,並且代表使用者身份的 cookie 在本地保存下來,所以下次再來 A 銀行網站時,不用重新登入
  2. 由於使用者沒有登出 A 銀行網站的帳戶,在瀏覽 B 惡意網站時,B 網站有個被設為透明的圖片,因為是透明的,所以使用者在畫面上看不到,然而該圖片包含一段惡意程式碼,程式碼如下。
// 備註:CSRF 攻擊手法有很多,此程式碼例子是一種最基本的攻擊方法之一
<img
  src="http://a-bank.com/transfer.do?acct=BadGuy&amount=100000 HTTP/1.1"
  width="0"
  height="0"
/>
  1. 使用者雖然將看不到此圖片, 但是,瀏覽器仍會向 http://a-bank.com/ 提交請求,同時此請求是帶有使用者的 cookie,所以 A 銀行可以辨識使用者身份,此惡意攻擊執行成功。
CSRF attack
CSRF attack

CSRF 防禦方法

加上驗證

在針對比較危險的操作,可以再增加一些驗證,像是圖形驗證碼、簡訊驗證碼等。

不要用 GET 請求來做關鍵操作

上面的透過把請求帶到圖片的例子,是很基本且常見的攻擊方式。這種攻擊之所以能很輕鬆做到,是因為使用了GET 請求進行操作。因此如果要避免 CSRF,最基本地做法,是不要用 GET 請求來做關鍵操作,建議用 POST 請求。

當然這不是說用 POST 請求就絕對安全,只是若使用 POST 請求,會需要有使用者的提交動作才能觸發。許多釣魚網站,都會引誘使用去點擊某些按鈕,正是因為要有點擊這個提交動作,才能觸發 CSRF 攻擊。雖然仍有可能被攻擊到,但起碼不會像用 GET 請求,使用者可能在完全不知情下,進到網站就馬上被攻擊。

檢查 Referrer

要能夠避免被跨站偽造請求,一個方式是先辨識發出請求的,是在哪個網站。即使有 cookie 等驗證使用者的機制,假如能夠辨別出不是來自於原本的網站,就能把偽造的請求過濾掉。在 HTTP 的標頭中有 Referrer 的字段,我們可以檢查這個字段,來確保請求不是來自於其他網站。

然而這做法也不是沒問題,因為這個字段的值,是由瀏覽器所提供,換句話說你的網站安全性,會依賴於瀏覽器這個第三方角色,假如某個瀏覽器的安全性做得不夠好,讓駭客能篡改 Referrer 的值,那仍有可能被攻擊成功。因此我們需要更安全的防禦方法。

CSRF token

用於認證身份的 cookie,因為會在每次發送請求時,被瀏覽器自動夾帶在請求中,這讓惡意網站也拿得到 cookie,所以可以拿來做偽造的請求。要避免被拿 cookie 來偽造請求,我們可以用 CSRF token。CSRF token 的做法,是讓網站用其他方式驗證使用者的身份,而不是透過 cookie。

CSRF token 需要由伺服器端生成,可以為每個請求或是每個 session 生成一次,但每個請求都生成會更為安全。接著,這個 token 會被傳送到客戶端,客戶端可以在表單中用隱藏字段儲存起來,客戶端當客戶端發出請求時,一起提交回伺服器端,或是作為 header 一部分傳回伺服器端。伺服器端需要在此用戶的請求紀錄或 session 中,找到該 token,如果客戶端提供的 token 與其不同,則拒絕請求。

<form action="/transfer.do" method="post">
<input type="hidden" name="CSRFToken" value="123token123">
[...]
</form>

瀏覽器本身防護 - SameSite cookies

由於許多 CSRF 攻擊是因為 cookie 被惡意網站使用,拿來偽造請求。假如要避免這發生,其實可以透過限定 cookie 只能被自己的網站使用。要如何限定 cookie 只能被自己網站用呢? 我們可以透過 SameSite cookies 來做到。

Google 在 Chrome 51 版之後加入的 SameSite Cookie 的功能,他只要將原本設置 Cookie 的方式後面加上 SameSite 即可。

SameSite cookies 是 HTTP 回應標頭中的 Set-Cookie 的屬性之一,此屬性的可能值為 Lax、Strict 或 None。Lax 或 Strict 值可以阻擋第三方網站攜帶 cookie 來防禦 CSRF 攻擊。最安全的做法是設定 Strict,Strict 會限制其他 Domain 來的任何請求都不帶上 Cookie,這樣一來 cookie 就只能自己的網站中使用,也就不用擔心被偽造請求。而 Lax 則是限制 POSTDELETEPUT 都不帶上 Cookie,GET 則會帶上 Cookie。

Set-Cookie: JSESSIONID=xxxxx; SameSite=Strict
Set-Cookie: JSESSIONID=xxxxx; SameSite=Lax

相關文章

🧵 如果你想收到最即時的內容更新,可以在 FacebookInstagram 上追蹤我們