CSRFとは何か。仕組みからトークン・SameSite Cookieによる対策まで実務目線で解説
対象の目安: Webアプリ開発者 / 実務レベル

CSRF(Cross-Site Request Forgery、クロスサイト・リクエスト・フォージェリ)は、利用者がログイン済みであることを悪用し、本人の意図しないリクエストを攻撃者がWebアプリへ送り込ませる攻撃です。SQLインジェクションやXSSのように「サーバーやページに不正なデータを差し込む」攻撃とは性質が異なり、CSRFが狙うのは「ブラウザが正規のリクエストに自動でCookieを付けて送る」という、Webの正常な仕組みそのものです。だからこそ、対策の考え方を一度きちんと理解しておかないと、的外れな防御をして安心してしまいがちです。
近年はSameSite Cookieという仕組みがブラウザ側で広く効くようになり、「もうCSRFは気にしなくてよいのでは」という声も聞かれます。しかし結論から言えば、SameSiteだけに頼るのは危険で、CSRFトークンなどアプリ側の対策と組み合わせるのが正しい姿です。この記事では、なぜCSRFが成立するのかという原理から、CSRFトークン(同期トークンパターン・ダブルサブミットCookie)とSameSite Cookieの活用、そして両者をどう組み合わせるかという多層防御の判断基準までを、実務目線で順を追って整理します。
CSRF対策の早見表
まず全体像をつかむために、代表的な対策を整理します。詳細は後続のセクションで掘り下げます。
| 対策 | 位置づけ | 仕組み | 主な注意点 |
|---|---|---|---|
| 同期トークンパターン | 根本対策 | サーバーがセッションに紐づくトークンを発行し、リクエストの値と照合する | 状態を持つ。トークンの漏えい・XSSに弱い |
| ダブルサブミットCookie | 根本対策(ステートレス向け) | 同じトークンをCookieとリクエスト両方に入れ、一致を確認する | 素朴な実装はCookie注入に弱く、署名付きが推奨 |
| SameSite Cookie | 多層防御 | クロスサイトからのリクエストにCookieを付けさせない | サブドメイン・ブラウザ実装差。単独の対策にしない |
| カスタムリクエストヘッダ | 補助(API向け) | 独自ヘッダの付与を要求し、CORSプリフライトを利用して防ぐ | 単純リクエストの範囲では効かない場合がある |
| 再認証・重要操作の確認 | 補助 | 送金・退会など重要操作でパスワードや確認を挟む | UXとのバランス。一般のCSRF対策の代替にはならない |
なぜCSRFは成立するのか
問題の核心は、ブラウザがCookieを「リクエスト先のサイト」に対して自動的に付与する、という挙動にあります。利用者があるサービスにログインすると、サーバーはセッションを識別するCookieをブラウザに保存させます。以後、そのサービス宛てのリクエストには、ブラウザがこのCookieを自動で付けます。これはログイン状態を保つための正常な仕組みです。
ここで攻撃者は、利用者を罠ページに誘導します。罠ページには、標的サービス宛てにリクエストを送るHTMLが仕込まれています。たとえば次のようなフォームを、JavaScriptで自動送信させます。
<!-- 攻撃者の罠ページに仕込まれたフォーム(例: 送金操作を狙う) -->
<form action="https://bank.example/transfer" method="POST">
<input type="hidden" name="to" value="attacker">
<input type="hidden" name="amount" value="100000">
</form>
<script>document.forms[0].submit();</script>
このフォームが送信されると、宛先は標的サービスなので、ブラウザは標的サービスのログインCookieを自動で付けてリクエストを送ります。サーバーから見ると、正しいCookieが付いた、文法的にも正しいリクエストが届くだけです。それが本人の意思で送られたのか、罠ページから送らされたのかを、Cookieだけでは区別できません。命令そのものは正しく、ただ「誰の意図か」という一点だけがすり替わっている。これがCSRFの本質です。
重要なのは、攻撃者は利用者のCookieの中身を盗む必要がない、という点です。盗まなくても、ブラウザが勝手に付けてくれます。だからHTTPSで通信を暗号化していても、Cookieに HttpOnly を付けていても、それだけではCSRFは防げません。これらはCookieの盗み出しを防ぐ対策であって、ブラウザが自動でCookieを付ける挙動そのものは止めないからです。
何が起こりうるのか(影響)
CSRFが狙うのは「状態を変える操作」です。単に画面を表示するだけのGETリクエストは、本来副作用がないため標的になりにくく、副作用のある操作こそが危険です。
| 影響 | 具体例 |
|---|---|
| 設定の改ざん | メールアドレスや通知先の変更、公開範囲の変更 |
| 認証情報の乗っ取り | パスワード変更、メールアドレス変更による乗っ取りの足がかり |
| 金銭的被害 | 送金、ポイント移転、商品の購入・発注 |
| データの破壊 | 退会、投稿やファイルの削除 |
| 権限の悪用 | 管理画面での権限付与・ユーザー追加(管理者を狙うCSRF) |
特に注意したいのは、メールアドレス変更とパスワード変更です。この二つをCSRFで突かれると、攻撃者は本人をアカウントから締め出して乗っ取れます。重要操作ほど、後述する再認証などの追加防御を重ねる価値があります。
注意
CSRFの検証は、必ず自分が管理する環境、または明示的に許可を得た対象に対してのみ行ってください。他人のサービスに対して罠ページからリクエストを送り込む行為は、不正アクセス禁止法をはじめとする法令に抵触するおそれがあります。本記事の手法はすべて、自社サービスの防御を確認する目的で理解してください。
根本対策(1)同期トークンパターン
最も基本的な根本対策が、CSRFトークン(同期トークン、Synchronizer Token Pattern)です。考え方はシンプルで、「攻撃者が知り得ない秘密の値」をリクエストに含ませることを必須にします。罠ページの攻撃者は、利用者のセッションに紐づくこの秘密を知らないため、正しいリクエストを組み立てられません。
具体的には次のように動きます。サーバーは、フォームを表示するときに、セッションに紐づく予測不能なトークンを生成し、隠しフィールドに埋め込みます。
<form action="/transfer" method="POST">
<input type="hidden" name="csrf_token" value="9f3a...(予測不能なランダム値)">
<input type="text" name="to">
<input type="text" name="amount">
<button type="submit">送金</button>
</form>
リクエストを受け取ったサーバーは、送られてきた csrf_token の値と、セッションに保存しておいた値が一致するかを照合します。一致しなければ拒否します。罠ページはこのトークンの値を知らないため、攻撃は成立しません。
トークンを正しく機能させるための条件がいくつかあります。
- 予測不能であること: 暗号論的に安全な乱数で生成します。連番や時刻ベースの推測できる値は避けます。
- セッションに紐づくこと: あるユーザーのトークンが、別のユーザーのリクエストで通ってはいけません。
- 状態を変えるリクエストに必須にすること: POST/PUT/PATCH/DELETEなど副作用のある操作すべてで照合します。GETには付けないのが原則です(後述)。
なお、多くのWebフレームワークはこの仕組みを標準で備えています。自前で実装するより、フレームワークのCSRF対策機能を正しく有効化するほうが安全です。
メモ
トークンをGETリクエストのURLパラメータに載せるのは避けてください。URLはアクセスログやReferer、ブラウザ履歴に残りやすく、トークンが漏えいする経路になります。トークンはPOSTのボディやリクエストヘッダで送るのが基本です。
根本対策(2)ダブルサブミットCookie
セッションにトークンを保存する同期トークンパターンは「状態を持つ」方式です。これに対し、サーバー側に状態を持ちたくない(ステートレスにしたい)場合に使われるのが、ダブルサブミットCookieです。
仕組みはこうです。サーバーは同じトークンを二つの経路で持たせます。一つはCookie、もう一つはリクエスト(ヘッダや隠しフィールド)です。サーバーは、Cookieの値とリクエストの値が一致するかだけを確認します。罠ページの攻撃者は、ブラウザが自動で付けるCookieは送らせられても、その値を読み取ってリクエスト側に同じ値を入れることはできません(別サイトのCookieはJavaScriptから読めないため)。だから一致させられず、攻撃は失敗します。
ただし、素朴なダブルサブミットCookieには弱点があります。サブドメインなどから攻撃者がCookieを書き込めてしまう「Cookie注入」が起きると、攻撃者が自分の知る値をCookieに入れ、同じ値をリクエストにも入れることで照合を突破できてしまいます。
実装する場合は、トークンにセッション情報を含めてHMACで署名し、サーバー側でその署名を検証する署名付き方式を採用してください。単に「CookieとリクエストでトークンSが一致すればよい」という素朴な実装は、サブドメインを攻撃者に取られた状況などで破られる可能性があります。
多層防御の柱: SameSite Cookie
ここまでがアプリ側の根本対策でした。これに重ねる強力なブラウザ側の防御が、SameSite Cookie属性です。Cookieに SameSite 属性を付けると、そのCookieをクロスサイト(別サイト)からのリクエストに付けるかどうかをブラウザが制御します。値は次の三つです。
| 値 | 挙動 |
|---|---|
| Strict | 別サイトからのリクエストには一切Cookieを付けない。リンクをたどった遷移でも付かない |
| Lax | 別サイトからの「安全なメソッド(GET等)かつトップレベル遷移」のときだけ付ける。POST等の副作用操作には付けない |
| None | 別サイトからのリクエストにも付ける。利用には Secure 属性が必須 |
CSRFの多くはPOSTなど副作用のあるリクエストを別サイトの罠ページから送らせる攻撃なので、SameSite=Lax でも罠ページからのPOSTにはCookieがつかなくなりCSRFが大きく抑えられます。SameSite=Strict ならさらに厳格ですが、外部リンクから自サイトに来た直後にログイン状態が引き継がれないなど、利用者体験に影響することがあるため、用途に応じて使い分けます。
SameSiteを「単独の対策」にしてはいけない理由
SameSiteは強力ですが、これだけに頼るのは危険です。OWASPも、SameSiteはCSRFトークンの代わりではなく、トークンと共存させてより堅牢に守るものだ、と明言しています。理由を整理します。
- 登録可能ドメイン単位で効く: SameSiteの判定は「サイト(登録可能ドメイン)」単位であり、オリジン単位ではありません。
a.example.comとb.example.comは同一サイト扱いになるため、信頼できないサブドメインがあると、そこからのリクエストは「同一サイト」とみなされて防げません。 - 既定値や挙動にブラウザ差・経緯がある: 多くのブラウザがSameSite未指定時の既定をLax相当として扱いますが、その挙動には経緯や例外があり、すべての環境で同一とは限りません。明示的に属性を設定するのが安全です。
- クライアントサイドCSRFには効かない: 自サイト内のJavaScriptの不備を突く形のCSRFには、SameSiteは保護を提供しません。
「SameSite=Laxが既定で効くようになったと聞いて、CSRFトークンの実装を外そうかと検討したことがあります。ただ調べてみると、自社は複数のサブドメインを運用していて、その一部は外部ベンダーに委託していました。サブドメインが同一サイト扱いになる以上、SameSiteだけでは守りきれないと分かり、トークンは残す判断にしました。」
トークン認証のAPIとCSRF
近年のSPAやモバイル向けのAPIでは、認証情報をCookieではなく、Authorization: Bearer ... のようなヘッダにトークンを載せて送る設計が広く使われます。この方式は、原理的にCSRFの影響を受けにくいのが特長です。
理由は単純で、CSRFはブラウザがCookieを「自動で」付ける挙動を悪用する攻撃でした。一方、Authorizationヘッダのトークンは、JavaScriptが明示的に付与しない限り送られません。罠ページのJavaScriptは、別オリジンであるAPIのトークンを保存場所から読み出して付与することができないため、攻撃が成立しにくくなります。
ただし、いくつか前提があります。
- トークンをCookieに保存して自動送信させると、結局CSRFの土俵に戻ります。Cookieに認証トークンを入れる設計を採るなら、Cookie認証と同様にCSRF対策が必要です。
- トークンをlocalStorage等に保存する場合は、今度はXSSのリスクが前面に出ます。XSSがあればトークンを盗まれるため、CSRF対策の代わりにXSS対策の重要度が上がる、というトレードオフを理解しておく必要があります。
つまり「APIだからCSRFは関係ない」と一律に言えるわけではなく、認証情報がどう運ばれるか(Cookie自動送信かヘッダ明示付与か)で判断するのが正しい見方です。
状態を変えないGETにしない、という設計上の原則
CSRF対策の土台として、設計段階で守るべき原則があります。それは「状態を変える操作をGETで実装しない」ことです。
GET /delete?id=10 のように、URLにアクセスするだけで削除や設定変更が起きる作りは、CSRFの格好の的になります。<img src="..."> を罠ページに置くだけで、利用者のブラウザに副作用のあるGETを送らせられるからです。HTTPの仕様(RFC 9110)でも、GETは「安全(safe)なメソッド」、すなわち取得が目的で状態を変えないものと定義されています。状態を変える操作は、慣例としてPOST/PUT/PATCH/DELETEなどの安全でないメソッドで扱います。この原則を守るだけで、攻撃面はかなり狭まります。
その上で、副作用のあるメソッドにCSRFトークンの照合を必須にし、Cookieに適切なSameSiteを設定する、という多層構成にします。
まとめると、どう組み合わせるか
整理すると、現実的なCSRF対策は次の重ね方になります。
- 1
設計で攻撃面を狭める
状態を変える操作はGETで実装せず、POST/PUT/PATCH/DELETEで行う。これが土台です。
- 2
根本対策としてCSRFトークンを入れる
フレームワークのCSRF対策機能を有効にする、または同期トークン・署名付きダブルサブミットCookieを正しく実装し、副作用のあるリクエストすべてで照合します。
- 3
SameSite Cookieを明示的に設定する
セッションCookieに SameSite=Lax(要件次第でStrict)と Secure、HttpOnly を明示的に付け、ブラウザ側の多層防御を効かせます。
- 4
重要操作には追加の確認を重ねる
パスワード変更・送金・退会などには、再認証や確認ステップを挟み、万一の突破に対する保険を用意します。
ここで強調したいのは、これらが「どれか一つを選ぶ」関係ではなく「重ねる」関係だという点です。 あわせて読みたい OWASP Top 10とは。開発者が押さえるべきWebの代表的リスクと対策を一気に理解する あわせて読みたい SQLインジェクションとは何か。仕組み・攻撃手法・影響・対策を原理から徹底解説
よくある質問
HTTPSにしていればCSRFは防げますか?
Cookieに HttpOnly を付ければCSRF対策になりますか?
SameSite=Lax が既定で効くなら、CSRFトークンは不要ですか?
GETリクエストにもCSRF対策は要りますか?
REST APIでトークン認証(Authorizationヘッダ)を使えばCSRF対策は不要ですか?
ダブルサブミットCookieは安全ですか?
まとめ
CSRF対策チェックリスト
- 状態を変える操作をGETで実装していないか(副作用はPOST等にしているか)
- 副作用のあるリクエストすべてでCSRFトークンを照合しているか
- トークンは予測不能でセッションに紐づき、URLに載せていないか
- ダブルサブミットCookieを使う場合、署名付き方式になっているか
- セッションCookieに SameSite・Secure・HttpOnly を明示的に設定しているか
- 信頼できないサブドメインがSameSiteの抜け道になっていないか確認したか
- パスワード変更・送金など重要操作に再認証などの追加防御を重ねているか
CSRFは、仕組みさえ理解すれば「正しいCookieが付いていても、それが本人の意図かどうかは別問題」という一点に集約されます。だからこそ、本人しか知り得ない秘密(トークン)をリクエストに要求し、ブラウザ側でもSameSiteで自動送信を絞る。この二段構えを土台に、重要操作には確認を重ねる。単一の魔法の対策を探すのではなく、原理に沿って多層で守ることが、CSRFに対する最も確実な構えです。
出典・参考
関連する記事
OWASP Top 10とは。開発者が押さえるべきWebの代表的リスクと対策を一気に理解する
Webアプリケーションの代表的なセキュリティリスクをまとめたOWASP Top 10について、その位置づけ、各カテゴリで何が問題になりどう防ぐか、そして開発プロセスへの組み込み方までを、開発者目線で具体例つきに解説します。
SQLインジェクションとは何か。仕組み・攻撃手法・影響・対策を原理から徹底解説
代表的なWeb脆弱性であるSQLインジェクションを、なぜ起きるのかという原理から、攻撃手法の分類、想定される影響、根本対策であるプレースホルダの使い方、多層防御、検出方法までを実務目線で網羅的に解説します。
XSS(クロスサイトスクリプティング)の仕組みと対策。反射型・格納型・DOM型を原理から整理
代表的なWeb脆弱性であるXSSを、なぜ起きるのかという原理から、反射型・格納型・DOM型の違い、想定される影響、根本対策である出力エスケープ(コンテキスト別エンコード)とCSPによる多層防御まで、実務目線で体系的に解説します。


