CSRF 跨站偽造請求
CSRF (Cross-site request forgery) 跨站偽造請求,駭客 利用使用者在 A 網 已驗証的身份,在使用者進入 第三網 (駭客架設) 時,發起對 A 網 隱藏式的請求指令 達成指定目的,而非透過 使用者 的意願。
圖片出處:creativegroundtech
- 登入 銀行網
- (成功) 取得使用者認證資料
- 駭客發送
釣魚網站
或惡意連結
給使用者 - 使用者到 駭客網站 不知情下,送出了到 銀行網 的指令請求
- 銀行依 2 取得的身份驗証,成功執行請求。
瀏覽器機制
當發出 請求 給某個網域,其網域關聯的 cookie
也會一起被帶上 請求 之中,所以駭客就是利用 cookie
中已驗證的身份,發動攻擊。
攻擊方式
GET
假設後台的 刪除 功能,可以直接以 /delete?id=3
來刪除 id=3
的項目。理論上,使用者必須先驗證過個人資料,且在後台操作才會執行 刪除。
html
<a href="/delete?id=3"> 刪除 </a>
標題 | 更新時間 | 操作 |
這是資料 | 2021-12-15 |
駭客行為
在使用者已登入過後台的情況下,對你發送 釣魚網站 、 惡意連結,在惡意網站內或連結中,寫入下面內容 (假設 後台 網址:https://www.admin.com
):
被動
進入網站後 「點擊」 執行 請求
html<a href="https://www.admin.com/delete?id=3">開始測驗</a>
當你點下時,就是到了
https://www.admin.com
且送出了 DELETE 指令,刪除了某個東西。主動
進入網站時,就 自動送出請求
html<img src="https://www.admin.com/delete?id=3" width="0" height="0" /> <a href="/test">開始測驗</a>
將
<img>
設為 隱藏,當網站進入後,就會請求url
,在不知情下就被攻擊了。
POST
如果刪除功能 是 POST
,駭客也可以使用 <form>
來主動提交表單,這是藉由 <iframe>
來隱藏 <form>
的表單顯示。stackoverflow
html
<iframe style="display:none" name="csrf-frame"></iframe>
<form
method="POST"
action="https://www.admin.com/delete"
target="csrf-frame"
id="csrf-form"
>
<input type="hidden" name="id" value="3" />
<input type="submit" value="submit" />
</form>
<script>
document.getElementById('csrf-form').submit()
</script>
當進入網站,就送出表單。
JSON 傳送
常見與後端溝通的 json
,也是有機會被攻擊,主要是透過 字元 組合達到指定的 json
樣式。
html
<form
action="https://small-min.blog.com/delete"
method="post"
enctype="text/plain"
>
<input name='{"id":3, "ignore_me":"' value='test"}' type="hidden" />
<input type="submit" value="delete!" />
</form>
會產生這樣的 請求 body
js
{
"id": 3,
"ignore_me": "=test"
}
提醒
但這個攻擊,是發生在 Content-Type: text/plain
的情況下,如果 服務端 有限定類型,是可以避免這個部分。
防禦方式
使用者
一般來說 CSRF 都是發生在使用者己經登入的狀態,才能發動偽造的請求。如果真的要避免,就是使用完網站就登出,這樣是可以避免,但不是很符合人性。
前端
圖形化驗證
在操作頁加上 圖形化驗証 ,「驗証成功」才可以請求操作,增加了發送請求的難度。
Cookie SameSite 同源設置
在設置
cookie
時,加上SameSite=Strict
會將 Cookie 限制在的 同源 (當下設置 cookie 的domain
才可以取得) 情況下使用。提醒
SameSite
的設置,還會影響寫入!!
後端
檢查 Referer
request
的Referer
可以看到發出請求的來源網址,服務端 可以由這位部分來判斷是不是合法的domain
。隱藏的
CSRF TOKEN
欄位在
<form>
表單裡,安插一個 隱藏的_csrf
欄位,而這個欄位的值就是由 服務端 所提供的「金鑰token
」,每次提交 請求 時,都會核對這個欄位的「值」是否與 服務端session
的token
相符。 且每次進都都會重新產生「金鑰」。html<form action="https://small-min.blog.com/delete" method="POST"> <input type="hidden" name="id" value="3" /> <input type="hidden" name="_csrf" value="1Zad3aedfaZdadfw" /> <input type="submit" value="送出" /> </form>
提示
express
針對CSRF
防範的工具 「 csurf 」,就是使用這個作法。注意
若你的 服務端,沒有限制發請求的
domain
,還是有可能被駭客拿到這個token
。
結論
其實最主要的防範方式,還是要 CSRF 驗証機製 加上 請求來源 來把關,更多層的機制「傷害」可以越低。