「そのリクエスト、本当に信用できますか?」Sec-Fetchヘッダーで守るアプリケーションの境界線
こんにちは。セキュリティの世界へようこそ。
日々、多くのエンジニアが「どうすればアプリケーションを安全に守れるのか」と頭を抱えています。XSS(クロスサイトスクリプティング)やCSRF(クロスサイトリクエストフォージェリ)といった攻撃の名前、一度は聞いたことがあるかもしれませんね。
今日は、そんな攻撃者たちの侵入を「ブラウザが自動的に教えてくれる身分証」を使って、スマートに防ぐ方法をお話しします。それが今回解説する「Fetch Metadata Request Headers」です。
1. 泥棒は「玄関」ではなく「隙間」を狙う
まず、セキュリティの基本を家に例えてみましょう。
XSSやCSRFは、いわば「あなたの家の鍵を盗んだ泥棒」や「近所の住人を装って玄関を開けさせる詐欺師」です。
- XSS(クロスサイトスクリプティング): 誰かがあなたの家の壁に「ここを押すと開くよ」という悪意ある落書きをし、それを見た家族がうっかり触ってしまうようなもの。
- CSRF(クロスサイトリクエストフォージェリ): あなたが信頼している隣人に「この封筒をあそこに届けて」と頼み、実はその封筒の中に「家の鍵を明け渡せ」という命令が隠されているようなものです。
これまで、私たちは「玄関(ログイン機能や権限管理)」を固く閉じることに集中してきました。しかし、現代のWebアプリケーションは複雑で、色々な場所からリクエストが飛んできます。そこで登場するのが、ブラウザが勝手に付与してくれる「身分証(Sec-Fetchヘッダー)」です。
2. 「Sec-Fetch-」ヘッダーという名の身分証
ブラウザは実はとても優秀で、あなたが何かリクエストを送るたびに、裏側で「これはどこから来たリクエストなのか?」「何のために送ったのか?」という情報を、こっそりヘッダーに書き込んでくれています。
これが「Sec-Fetch-Site」や「Sec-Fetch-Mode」です。
重要な3つの項目を覚えよう
1. Sec-Fetch-Site: 「どこから来たの?」
same-origin: 同じサイトから。安全!cross-site: 全く別のサイトから。ちょっと警戒が必要!
2. Sec-Fetch-Mode: 「何のために送ったの?」
navigate: ページ遷移。cors: 他のサイトとのデータ通信。
3. Sec-Fetch-Dest: 「何を受け取りたいの?」
document: HTMLページそのもの。script: JavaScriptのプログラム。
「知らない人(cross-site)から、いきなり家の鍵(document)を要求されたら拒否する」。この単純なルールをサーバーサイドに実装するだけで、多くの攻撃は未然に防げるのです。
3. 実践!サーバーサイドでの防御アーキテクチャ
では、実際にどのように防御するか、Webサーバー(ここでは擬似コードで表現します)での実装例を見てみましょう。
// サーバーサイドのミドルウェアのイメージ
function securityMiddleware(req, res, next) {
const site = req.get(‘Sec-Fetch-Site’);
const mode = req.get(‘Sec-Fetch-Mode’);
const dest = req.get(‘Sec-Fetch-Dest’);
// もし「外部サイトから」かつ「ドキュメント(ページ)を要求」しているなら、
// それはCSRF攻撃の可能性が高いのでブロックする!
if (site === ‘cross-site’ && dest === ‘document’) {
return res.status(403).send(‘不正なリクエストです。’);
}
// もし「外部サイトから」かつ「スクリプト」を読み込もうとしているなら警戒する
if (site === ‘cross-site’ && dest === ‘script’) {
console.warn(‘外部からのスクリプト読み込みを検知しました’);
// 必要に応じて制限を加える
}
next();
}
このように、リクエストが届いた瞬間に「身分証」を確認するだけで、攻撃者の手口を大幅に制限できます。これが「Fetch Metadata」による防御です。
4. なぜこれが「最強」に近いのか?
セキュリティの専門家がこの手法を好む理由は、「アプリケーション側のコードを大きく書き換えなくて済むから」です。
従来の対策(トークンの埋め込みなど)は、すべてのフォームに修正が必要で、漏れが発生しがちでした。しかし、このヘッダー確認は「玄関の門番」を一箇所設置するだけで、サイト全体を守ることができます。
防御のポイント
- デフォルトで拒否する: 怪しいリクエストはまず捨てる。
- 例外を管理する: 外部連携が必要なAPIだけ、明示的に許可する。
最後に:完璧な壁を作る必要はない
セキュリティは「完璧な城壁」を作ることではなく、「泥棒が侵入するコストを極限まで引き上げること」です。
攻撃者は楽な獲物を探しています。今回紹介したSec-Fetch-ヘッダーを確認する簡単な仕組みを入れるだけで、あなたのアプリケーションは「あそこは面倒な仕掛けがあるからやめておこう」と思わせる、強固な砦へと進化します。
まずは、あなたの開発しているWebサーバーのログを見て、「どんなSec-Fetchヘッダーが届いているか」を確認することから始めてみませんか?一歩ずつ、泥臭く、しかし確実に守りを固めていきましょう!
—
執筆:世界最高峰のセキュリティバイブル主筆ライターより
コメント