ある日UIを作る時に、ヘッダーが正しいのかをチェックするため、developer toolを見たら、ちょっと怪しいヘッダーを見つけました。
Set-Fetch-Mode
?何これ?って思う方がいるかもれませんが、一緒に調べてみましょう。
ちょっと変だなと思って、何か誤ってヘッダーを入れたのか?と思いましたが、あまり記憶にありませんでした。
自分のコードは結構シンプルなので、多分これはブラウザから入れたヘッダーということを考えました。
ググってみて、実はこれはFetch Metadata Request Headersという新しい仕様でした。今 Chrome だけこのヘッダーを入れる、他のブラウザはまだ入っていないようです。
CORSをもう一回理解しましょう
みんなさんご存知の通りに、ブラウザは怪しい人がブラウザーからデータを奪わないように、いくつかのポリシーがあります。例えば別のドメインのAPIを呼ぶ際、Access-Control-Allow-Origin
を正しく設定しないといけないことや、Preflight しないといけないません。詳しくはMDNに書いてあるので、詳細を知りたい人は見てみてください。
それでもいくつの欠点があります。<img>
タグは別のドメインにフェッチすることができ、もしsrcから怪しいクエストをしたらデータを奪うことが不可能ではありません。もちろん、サーバー側からちゃんとしたら、これらの攻撃も簡単に防げるでしょう。
もしブラウザからリクエストを送るときに、どこから来たという情報をmeta dataヘッダーに入れたら、サーバー側も判断することができます。
このための仕様が fetch-metadata-request
です。
標準仕様
今四つのヘッダーが仕様にあります
1. Sec-Fetch-Dest
どこからこのリクエストきましたっていうヘッダーです。可能な値は audio, document, font, image, object, serviceworkerなど。
このヘッダーさえあれば、サーバーはヘッダーによって、合法かどうかは判断できます。
もしこのリクエストがイメージタグからきた場合でもrouteは/api/my/profile/remove
だったら、おそらく hacker と思って良い。エラーコードを返すのが良いでしょう。
2. Sec-Fetch-Mode
このリクエストもモードは何でしょうか?っというヘッダーですが、cors, navigate, nested-navigated, no-corsなどあります。
fetch のmodeオプションと似ています。
3. Sec-Fetch-Site
リクエストは同じドメインなのか、crossドメインなのかを判断できる
4. Sec-Fetch-User
このヘッダーはbooleanで、リクエストが navigation requestに限り、ユーザーがスクリーンから操作があったらtrueになる。
ヘッダーを削除できるのか?
もし仕様になったら、forbidden headersになり、削除することができないと思われます。ブラウからコードを利用してヘッダーの値を変えることはできないので、サーバー側がこのヘッダーの値を信じて良いでしょう。
結論
古い環境で同じことをやりたい場合、自分でヘッダーの定義を制御して、偽造することもおかしくはありません。
仕様は、変えることが難しく 、同じ仕様があるため、サーバー側も実装しやすいです。これからアプリケーションの開発もより安全になるでしょう。