CSRF
ユーザーが認証済みの Web サイトに対して、攻撃者が意図しないリクエストを送信させる攻撃手法
CSRF とは
CSRF (Cross-Site Request Forgery、クロスサイトリクエストフォージェリ) は、ユーザーが認証済みの Web サイトに対して、攻撃者が用意した罠ページから意図しないリクエストを送信させる攻撃手法である。ブラウザが Cookie を自動送信する仕組みを悪用する。
OWASP Top 10 に長年ランクインしていた攻撃で、2013 年版では 8 位だった。SameSite Cookie の普及により脅威は低下したが、レガシーシステムや Cookie ベースの認証を使うアプリケーションでは依然として注意が必要だ。
攻撃の仕組み
攻撃は次の 4 ステップで成立する。
1. ユーザーが銀行サイト (bank.example.com) にログイン
→ セッション Cookie がブラウザに保存される
2. ユーザーが攻撃者の罠ページ (evil.example.com) を閲覧
3. 罠ページに埋め込まれた HTML が銀行サイトへ POST リクエストを自動送信
<form action="https://bank.example.com/transfer" method="POST">
<input type="hidden" name="to" value="attacker-account" />
<input type="hidden" name="amount" value="1000000" />
</form>
<script>document.forms[0].submit();</script>
4. ブラウザがセッション Cookie を自動付与
→ 銀行サイトは正規ユーザーからのリクエストと判断
→ 送金が実行される
攻撃者はユーザーの Cookie を盗む必要がない。ブラウザが自動的に Cookie を付与してくれるため、ユーザーが罠ページを開くだけで攻撃が成立する。
対策
CSRF トークン (Synchronizer Token Pattern)
フォームに一意なトークンを埋め込み、サーバーで検証する。最も伝統的で確実な対策だ。
<form action="/transfer" method="POST">
<input type="hidden" name="_csrf" value="a1b2c3d4..." />
<!-- フォームの内容 -->
</form>
攻撃者は CSRF トークンの値を知ることができないため、正しいトークンを含むリクエストを偽造できない。
SameSite Cookie
SameSite 属性を設定すると、クロスサイトリクエストに Cookie を送信しなくなる。
| 値 | 動作 | CSRF 防御 |
|---|---|---|
Strict | Cookie を設定したサイトと同一サイト起点のリクエストにしか送信しない | ほぼ防御 (同一サイト内の別オリジンを踏み台にされる経路は残る) |
Lax | 同一サイト起点に加えて、クロスサイトでは「トップレベルナビゲーション」かつ「安全なメソッド (GET など)」の両方を満たすリクエストにのみ送信する。画像・iframe・fetch() のクロスサイト GET や、クロスサイトの POST では送信しない | 条件付きで防御 |
None | 常に Cookie を送信 (Secure 必須) | 防御なし |
主要ブラウザは SameSite の指定がない Cookie を Lax として扱う。Chrome では 2020 年 2 月の 80 で入る予定だったが、Stable の初回ロールアウトには含まれず、その後の段階展開で有効化された。
ただし、この既定値を CSRF 対策として当てにするのは危険だ。既定として適用される Lax には緩和措置があり、発行から 2 分以内の Cookie はクロスサイトのトップレベル POST でも送信される。POST を使うログインフローが壊れるのを避けるための暫定的な介入で、Chrome は将来の削除を予告している。つまりログイン直後の 2 分間だけ穴が開き、SameSite=Lax を明示した Cookie とは挙動が違う。加えて、GET リクエストで副作用を起こす API (GET /delete-account) は Lax でも防御できない。属性は既定に頼らず明示的に指定し、トークン検証と併用する。
Origin / Referer ヘッダー検証
リクエストの Origin ヘッダーが自サイトのドメインと一致するか検証する。CSRF トークンの管理が不要で実装が簡単だ。現代のブラウザはクロスオリジンのリクエストと、同一オリジンでも GET / HEAD 以外のメソッドのリクエストに Origin を付与する。ただしリダイレクトを経由した場合やサンドボックス化された文書からの送信では値が null になり、間にあるプロキシがヘッダーを落とすこともある。ヘッダーが無いリクエストを通す実装にすると検証そのものが無意味になるため、欠落は拒否側に倒す。Referer はパスまで含むため送信抑止を受けやすく、Origin を主にして Referer は補助に留めるのが実務的だ。
SPA + API 構成での CSRF
SPA が JWT を Authorization ヘッダーで送信する構成では、ブラウザが自動送信しないため CSRF のリスクは低い。
| 認証方式 | CSRF リスク | 理由 |
|---|---|---|
| セッション Cookie | 高い | ブラウザが自動送信 |
| JWT in Cookie | 高い | ブラウザが自動送信 |
| JWT in Authorization ヘッダー | 低い | JavaScript で明示的に付与 |
| JWT in localStorage | 低い (XSS リスクあり) | ブラウザが自動送信しない |
JWT を Cookie に保存する場合は、SameSite=Strict と CSRF トークンの併用が推奨される。
API Gateway + Lambda での対策
先に押さえておきたいのは、CORS 設定そのものは CSRF を止めないという点だ。Content-Type が application/x-www-form-urlencoded / multipart/form-data / text/plain のいずれかで、独自ヘッダーを持たないリクエスト (罠ページのフォーム送信と同じ形) はプリフライトが飛ばず、サーバーまで到達する。ブラウザが遮るのはレスポンスの読み取りだけなので、送金や削除といった副作用は起きてしまう。Fetch 仕様がこの形にサーバーの同意を要求しないのは、サーバー側が CSRF 対策済みである前提を置いているからである。
そのうえで、CORS 設定では Access-Control-Allow-Origin を自サイトのドメインに限定する。* (ワイルドカード) は使わない。Cookie を伴うリクエスト (AllowCredentials: true) に対しては、仕様上そもそも * を返せず、オリジンを明示する必要がある。
# SAM テンプレート
Cors:
AllowOrigin: "'https://example.com'"
AllowMethods: "'GET,POST,PUT,DELETE'"
AllowHeaders: "'Content-Type,Authorization'"
AllowCredentials: true
CORS はブラウザが強制する仕組みであり、curl やサーバーサイドからのリクエストは制限できない。CSRF を止めるのは Cookie 側の SameSite 指定とトークン検証・Origin 検証であって、CORS 設定は JavaScript からの読み取りを絞る別系統の防御である。両者を混同せず、認証・認可も含めて多層で実装する。
CSRF を扱う関連書籍も多い。
この記事は役に立ちましたか?
関連用語
CORS
ブラウザの同一オリジンポリシーを緩和し、異なるオリジン間のリソース共有を許可する仕組み
JWT
JSON Web Token の略で、署名付きの JSON でユーザー情報を安全に伝達するトークン形式
Cookie
Web サーバーがブラウザに保存を指示し、リクエスト間で状態を維持する仕組み
セキュリティヘッダー
HTTP レスポンスヘッダーでブラウザのセキュリティ機能を制御し、XSS やクリックジャッキングを防ぐ仕組み
Fetch API
HTTP リクエストを送信するためのモダンな Web API で、XMLHttpRequest の後継
Web アプリケーション
ブラウザを通じて利用するアプリケーション。インストール不要で幅広い端末で動く
関連する記事
技術書を Kindle で読むコツ - 電子書籍ならではの活用術
技術書を Kindle で効率的に読むための具体的なテクニックを紹介します。ハイライト、検索、フォントサイズの調整など、紙にはない電子書籍の強みを活かす方法。
技術書の読む順番戦略 - 複数冊を組み合わせて理解を加速させる
技術書を 1 冊ずつ読むのではなく、複数冊を戦略的に組み合わせることで、1 冊では届かない理解の深さと広さに達する方法を解説します。
技術書のタイトルに隠された法則 - 「入門」「実践」「詳解」の意味を読み解く
技術書のタイトルに使われる「入門」「実践」「詳解」などのキーワードには暗黙のルールがあります。タイトルだけで本のレベルと内容を見抜くコツを紹介します。