什麼是 CSRF 攻擊?如何防範?
2023年2月9日
在 《什麼是 XSS 攻擊?如何防範?》 這篇文章中,我們討論到什麼是 XSS 以及防禦方法,在這篇文章我們會繼續討論另一種常見的網路攻擊方式 - 跨站請求偽造 Cross Site Request Forgery (CSRF)。
什麼是 CSRF 攻擊?
CSRF 是指跨站的請求偽造,這種攻擊方法會強迫使用者在他們已經驗證身份的網站中,執行某些惡意的偽造操作,因為已經驗證過該使用者,所以網站就會以操作來自該使用者,因此接受了該操作。舉例來說,某個使用者登入銀行帳戶後,去逛別的網站,但不小心點開惡意網站,該惡意網站中的程式碼用這名使用者的名義,進行未經同意的轉帳操作。
CSRF 之所以成立,是因為使用者的身份已經先被驗證過。如果要白話一點理解,就像是別人偷拿你的會員點數卡去買東西。但因為店家認卡,所以當看到小偷拿著你的卡,就相信小偷是你本人,於是接受該小偷使用你的點數進行消費。
CSRF 攻擊流程
Step1: 使用者成功登入 A 銀行網站的帳戶,並且代表使用者身份的 cookie 在本地保存下來,所以下次再來 A 銀行網站時,不用重新登入
Step2: 由於使用者沒有登出 A 銀行網站的帳戶,在瀏覽 B 惡意網站時,B 網站有個被設為透明的圖片,因為是透明的,所以使用者在畫面上看不到,然而該圖片包含一段惡意程式碼,程式碼如下。
// 備註:CSRF 攻擊手法有很多,此程式碼例子是一種最基本的攻擊方法之一
<img
src="http://a-bank.com/transfer.do?acct=BadGuy&amount=100000 HTTP/1.1"
width="0"
height="0"
/>
Step3: 使用者雖然將看不到此圖片, 但是,瀏覽器仍會向 http://a-bank.com/
提交請求,同時此請求是帶有使用者的 cookie,所以 A 銀行可以辨識使用者身份,此惡意攻擊執行成功。
CSRF 防禦方法
1. 加上驗證
在針對比較危險的操作,可以再增加一些驗證,像是圖形驗證碼、簡訊驗證碼等。
2. 不要用 GET
請求來做關鍵操作
上面透過把請求帶到圖片的例子,是很基本且常見的攻擊方式。這種攻擊之所以能很輕鬆做到,是因為使用了 GET
請求進行操作。因此如果要避免 CSRF,最基本地做法,是不要用 GET
請求來做關鍵操作,建議用 POST
請求。
當然這不是說用 POST
請求就絕對安全,只是若使用 POST
請求,會需要有使用者的提交動作才能觸發。
許多釣魚網站,都會引誘使用者去點擊某些按鈕,正是因為要有點擊這個提交動作,才能觸發 CSRF 攻擊。雖然仍有可能被攻擊到,但起碼不會像用 GET
請求,使用者可能在完全不知情下,進到網站就馬上被攻擊。
3. 檢查 Referrer
要避免跨站偽造請求,可以辨識請求來自哪個網站。除了使用 cookie 等驗證機制,如果能夠辨別出請求不是來自原本的網站,也能過濾掉偽造請求。在 HTTP 的標頭中有 Referrer 字段,我們可以檢查這個字段,來確保請求不是來自其他網站。
然而,這做法也不是完全無問題,因為這個字段的值是由瀏覽器提供的。如果某個瀏覽器的安全性不足,讓駭客能篡改 Referrer 值,那仍有可能被攻擊成功。因此我們需要更安全的防禦方法。
4. CSRF token
用於認證身份的 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>
5. 瀏覽器本身防護 - SameSite cookies
由於許多 CSRF 攻擊是因為 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 則是限制 POST
、 DELETE
、PUT
都不帶上 Cookie,GET
則會帶上 Cookie。
Set-Cookie: JSESSIONID=xxxxx; SameSite=Strict
Set-Cookie: JSESSIONID=xxxxx; SameSite=Lax