Kalan's Blog

Kalan 頭像照片,在淡水拍攝,淺藍背景

四零二曜日電子報上線啦!訂閱訂起來

本部落主要是關於前端、軟體開發以及我在日本的生活,也會寫一些對時事的觀察和雜感
本部落格支援 RSS feed(全文章內容),可點擊下方 RSS 連結或透過第三方服務設定。若技術文章裡有程式碼語法等特殊樣式,仍建議至原網站瀏覽以獲得最佳體驗。

目前主題 亮色

我會把一些不成文的筆記或是最近的生活雜感放在短筆記,如果有興趣的話可以來看看唷!

更安全的請求標頭 - Fetch Metadata Request Headers

有一天在開發頁面的時候,為了要檢查請求 Header 的欄位是否正確,打開開發工具一看,發現了請求多出了幾個可疑的 header:

network

有注意到可疑的地方嗎?仔細一看發現,怎麼有三個以 Sec-Fetch-* 開頭的標頭。 這引起了我的注意,我並沒有設定這些標頭,也沒有套用其他函式,為什麼會自己幫我加上這些標頭,猜測應該是瀏覽器在作祟。

查了一下 google 發現,原來這是一個新的草案,叫做 Fetch Metadata Request Headers。目前只有 chrome 才會加上這些標頭,Firefox, Safari 並不會。

再談同源政策(CORS)

我們都知道,瀏覽器為了防止一些有心人士用奇怪的手法竊取你的資料,限制了某些來源的存取條件,例如跨域請求時需要加上 Access-Control-Allow-Origin 或是 Preflight 請求等等,詳細的內容可以參考我之前寫的「如何和 CORS 與 Cookie 打交道」。

儘管如此還是有些缺陷,像是 <img/> 仍然可以送出跨域請求,這樣有心人士就可以略過 CORS 的限制。當然,如果伺服器有做好基本的防護措施,還是可以擋下大部分不安全的請求。

如果可以再送出請求的時候,加上一些額外的標頭資訊(metadata)描述這個請求是從哪裡來的話,伺服器也可以根據標頭來做適當的回應,於是誕生出這樣的草案。

標頭規格:

目前主要有四個標頭在草案當中:

1. Sec-Fetch-Dest

代表這個請求的目的地是哪裡。

可能的值有 audio、document、font、image、object、serviceworker 等等。這樣有幾個好處,有了這些 header 的判斷,伺服器馬上就可以知道這個請求來源是否合法,例如如果這個來源是從 <img> 來的,卻不是跟伺服器要圖片,那麼十之八九是駭客,我們就可以直接回應錯誤給他。

2. Sec-Fetch-Mode

代表請求的模式。主要有 cors、navigate、nested-navigate、no-cors 等等,來判斷這個請求的模式是什麼,類似 fetch 當中的 mode。

像是 Set-Fetch-User 我們也可以知道使用者是否是透過操作(例如點擊、鍵盤等等)來發出請求的。

3. Sec-Fetch-Site

代表請求的來源是同源還是跨域。

4. Sec-Fetch-User

這個標頭的值是布林值,只有在請求是只有在 navigation request(request 的目的地為 document)而且有互動時(例如按下按鈕、鍵盤等等)才會是 true,伺服器可以根據這個標頭來判斷使用者觸發請求的方式是否合法。

像是點擊 form 表單送出的時候,因為是由 document 送出請求,且使用者有互動(點擊按鈕送出),所以 Set-Fetch-User 會是 ?T

有辦法把標頭拿掉嗎?

如果成為規範之一的話,可能沒有辦法把它拿掉。另外你不可以透過手動設定來改寫標頭的值,因為它屬於 forbidden headers 之一。

結論

以往要做到類似的事情,都會用自定義的 header 來防範,但還是有可能被偽造,而且加上自定義的標頭就需要做 prelight 的檢查,又多了一份工。從規範下手的好處在於這些標頭沒辦法被輕易改寫,而且提供了統一的標準,有了這些標頭,就可以讓後端在收到請求時多做一些判斷,進而提高安全性。

上一篇

如何搜集並集中 golang 應用中的 Log

下一篇

透過 overflow-anchor 實作 pin to bottom 元件

如果覺得這篇文章對你有幫助的話,可以考慮到下面的連結請我喝一杯 ☕️ 可以讓我平凡的一天變得閃閃發光 ✨

Buy me a coffee