【入門編】ダブルサブミットクッキー法によるステートレスなCSRF対策 – アプリケーションセキュリティ & 安全な開発防御ガイド

玄関の鍵を閉めても「勝手に開けられる」?CSRFという泥棒の手口と、その対策

こんにちは。セキュリティの世界へようこそ。
日々、開発の現場で「セキュリティ対策をしましょう」と言われても、「正直、何から手をつけていいか分からない」「専門用語が多すぎて頭がパンクしそう」なんて感じていませんか?

今日は、そんな皆さんと一緒に「CSRF(クロスサイト・リクエスト・フォージェリ)」という、ちょっとずる賢い泥棒の手口と、それを防ぐための「ダブルサブミットクッキー法」というテクニックを、身近な例えを使って紐解いていきましょう。

—

CSRFってどんな泥棒?:鍵を盗まずに家に入る方法

まずはCSRFの仕組みをイメージしてみましょう。

皆さんが家(Webサービス)に帰ってきて、鍵を開けて入ったとします。このとき、皆さんは「鍵を持っている人=本人」として、家の中で自由に過ごせますよね。Webの世界で言えば、ログインして「セッションクッキー」という鍵を持っている状態です。

ところが、ここに「偽物のあなた」がやってきたらどうなるでしょう?
泥棒はあなたの鍵を盗む必要はありません。あなたが鍵を開けて家に入った瞬間に、背後からこっそり忍び込んで、あなたのフリをして「この家を売ってくれ!」といった命令を勝手に実行させる。これがCSRF(クロスサイト・リクエスト・フォージェリ)です。

「ブラウザが自動的にクッキー(鍵)を送信してしまう」という便利な機能の裏をかいた、非常に厄介な攻撃なんです。

—

「ダブルサブミットクッキー法」で防犯を強化する

サーバー側に「誰がログインしているか」という情報をいちいち保存したくない(ステートレスな環境にしたい)とき、どうやって「その命令は本当に本人が出したものか?」を見極めるのでしょうか。

ここで登場するのが「ダブルサブミットクッキー法」です。
これは、家に入る際に「合言葉」を2つ要求するような仕組みです。

1. クッキーに秘密の値を保存する(家の中に置いたメモ)
2. リクエストのパラメータにも同じ値を入れる(玄関で提示する合言葉)

サーバーは、「クッキーに入っている値」と「リクエストで送られてきた値」が完全に一致するかをチェックします。泥棒はあなたのクッキーは使えても、別のドメインから送るリクエストに「クッキーと同じ値」をコピーして書き込むことは、ブラウザのセキュリティ制限(同一生成元ポリシー)のおかげでできません。

つまり、「自分しか知らないはずの合言葉を、リクエストの中にも書けるか?」というテストで本人確認を行うわけです。

—

実装のイメージ:コードで見る防犯対策

実際にWebアプリケーションでこの仕組みをどう書くのか、シンプルな例を見てみましょう。

// 1. クッキーにランダムな値をセット(例: CSRFトークン)
// サーバー側で発行し、JavaScriptから読み取れるようにします
document.cookie = “csrf_token=abc123xyz789; path=/; SameSite=Lax”;

// 2. リクエストを送る際に、クッキーの値を「ヘッダー」か「パラメータ」に添える
// 攻撃者は他のサイトからこの値を読み取れないため、偽装が不可能になります
fetch(‘/api/update-profile’, {
method: ‘POST’,
headers: {
‘Content-Type’: ‘application/json’,
// ここが重要!クッキーと同じ値をヘッダーにも含める
‘X-XSRF-TOKEN’: ‘abc123xyz789’
},
body: JSON.stringify({ name: ‘新しい名前’ })
});

サーバー側では、受け取ったリクエストの X-XSRF-TOKEN ヘッダーと、送られてきた csrf_token クッキーを比較し、一致しなければ「不審なリクエストだ!」として拒否するだけです。

—

注意点:サブドメインの「合鍵」に気をつけろ!

ここで一つ、プロとして絶対に伝えておきたい「盲点」があります。

もし皆さんのサイトが app.example.com で、同じドメイン内に blog.example.com のような他のサイトが存在する場合、注意が必要です。
Cookieの仕様上、サブドメイン間でクッキーが共有されてしまうことがあります。もし blog.example.com に脆弱性があり、攻撃者に悪用されると、そこからメインの app.example.com に有効なクッキーを書き込まれてしまうリスクがあるのです。

対策のヒント:

  • Cookieの Domain 属性を絞る: 不要に広い範囲でクッキーを有効にしない。
  • SameSite属性を使う: 最近のブラウザなら SameSite=Lax や Strict を指定するだけで、CSRFの多くは防げます。これは「玄関のドアをそもそも開けにくくする」強力な防犯扉です。

—

最後に:セキュリティは「完璧」より「継続」

セキュリティに100%の絶対はありません。しかし、今回紹介したダブルサブミットクッキー法のように、攻撃者が「手間がかかるし、盗むのが難しい」と感じる仕組みを積み重ねることが、何よりの防御になります。

最初は難しく感じるかもしれませんが、まずは「リクエストの中に、自分だけが知っている秘密の証拠を混ぜる」という仕組みを意識してみてください。それだけで、皆さんの書くコードはグッと強固になりますよ。

一歩ずつ、一緒に学んでいきましょう!何か分からないことがあれば、いつでもまた聞きに来てくださいね。

コメント

タイトルとURLをコピーしました