1. イントロダクション:CSRFとは?
CSRFが危険な理由
CSRF(Cross-Site Request Forgery)は、日本語で「クロスサイト・リクエスト・フォージェリ」と呼ばれています。これは、ログイン中のユーザーになりすまし、意図しないリクエストを強制的に実行させる攻撃です。
攻撃者はユーザーのセッションクッキーを利用します。したがって、正規のユーザーが行える操作(パスワード変更、退会、送金など)を自由に行えるのです。対策は必須です。なぜなら、認証(ログイン)や認可(権限)の仕組みだけでは防げない、Webアプリケーションの脆弱性の一つだからです。
2. 攻撃の仕組みと原理
CSRF攻撃は、基本的に以下の3つの前提条件が揃ったときに成立します。
- ログイン状態: ユーザーが攻撃対象のWebサイトAにログインしている必要があります。
- ブラウザの自動送信: ブラウザは、サイトAへのリクエストに対し、自動的にセッションクッキーを付与して送信します。
- 予測可能なリクエスト: さらに、攻撃者がサイトAで実行させたい操作(例: パスワード変更)のリクエスト内容を完全に予測できることが条件です。
攻撃の具体的な流れ
- 攻撃者が「罠のサイトB」を作成します。その中にサイトAへのリクエストを仕込みます(例:
<img src="https://サイトA.com/change_pass?new_pass=hacked">)。 - ログイン中のユーザーがサイトBを訪問します。
- すると、ブラウザは罠のコードを読み込みます。このとき、セッションクッキーを付けてサイトAへリクエストを自動送信します。
- 結果として、サイトAは正規ユーザーからのリクエストと誤認します。そして、パスワード変更を実行してしまうのです。
【 CSRF攻撃の仕組みと原理 】
+-------------------+ (1) ユーザーは正規サイトAにログイン中 +-------------------+
| ユーザーのブラウザ | <---------------------------------------------- | 正規サイトA |
| (ログイン済み) | (セッションクッキーを保持) | (銀行、ECサイト等) |
+---------+---------+ +---------+---------+
| ^
| (2) ユーザーが罠サイトBを訪問する |
v |
+---------+---------+ (3) 罠サイトBに仕込まれたHTMLタグ/JSが +---------+---------+
| 罠サイトB | <--------------------------------------------- | (ユーザーのブラウザ)|
| (攻撃者が用意) | 不正なリクエストを自動送信 | (自動でセッション) |
+---------+---------+ +---------+---------+
| |
| |
| (4) ブラウザがセッションクッキーを自動付与して |
| 不正リクエストを正規サイトAへ送信 |
+-------------------------------------------------------------------+
↓
+-------------------+
| 正規サイトA |
| (銀行、ECサイト等) |
+---------+---------+
|
(5) 正規リクエストと誤認し
操作を実行してしまう
↓
+-------------------------------+
| パスワード変更、送金、購入など |
| ユーザーが意図しない操作 |
+-------------------------------+
3. 🛡️ 完璧を目指す!CSRFに対する7つの防御策
CSRFの防御策は、「攻撃者が予測できない情報をリクエストに含める」こと、または「外部サイトからのリクエストを受け付けない」ことに焦点を当てることが重要です。
対策1: トークンによる防御(最も一般的で強力)
CSRFトークンと呼ばれる予測不能なワンタイムの値をフォームに埋め込みます。そして、サーバー側で検証を行います。
- サーバー側: まず、フォーム表示時にランダムなトークンを生成し、ユーザーのセッションに保存します。
- フォーム側: 次に、トークンを隠しフィールド
<input type="hidden">としてフォームに埋め込みます。 - サーバー側: 最後に、リクエスト受信時、フォームの値とセッションの値を比較します。一致しなければリクエストを拒否します。
対策2: SameSite Cookie属性の利用
Cookieに SameSite 属性を設定します。これにより、外部サイトからのリクエスト時にセッションクッキーが送信されるのを制限できます。
SameSite=Lax: ほとんどの外部サイトからのGETリクエストにはCookieを送信しません。これは実用的な安全性を提供します。SameSite=Strict: 外部サイトからのリクエストでは、いかなる場合もCookieを送信しません。これは最も安全ですが、ユーザー体験(UX)に影響を与える可能性があります。
対策3: カスタムヘッダーによる検証
POSTリクエスト時に、JavaScriptで生成したカスタムヘッダー(例: X-Requested-With: XMLHttpRequest)を付与します。その後、サーバー側でそのヘッダーが存在するかをチェックします。
対策4: Refererヘッダーによる検証
リクエストの送信元URLを示す Refererヘッダーを確認します。自サイトのURLでなければ拒否する方法です。
- 注意点: ただし、ユーザーやブラウザの設定によってはRefererヘッダーが送信されない場合があります。そのため、この対策を単独で使用することは避けるべきです。
対策5: 二段階認証やCAPTCHAの導入
送金や退会など、特に重要な処理を行う直前に対策を導入します。具体的には、パスワードの再入力やCAPTCHA認証を要求します。これにより、攻撃者が操作を自動実行するのを防ぐことが可能です。
対策6: GETリクエストでの状態変更を禁止する
サービス内で、ユーザーの状態を変更する処理(パスワード変更、削除、送金など)は必ずPOSTやPUT、DELETEリクエストで行うように徹底してください。なぜなら、GETリクエストはブラウザから簡単に偽装できるからです。
対策7: 開発フレームワークの活用
現代の主要なWeb開発フレームワーク(Laravel, Ruby on Rails, Django, Springなど)は、CSRF対策としてCSRFトークン認証機能を標準で組み込んでいます。そのため、設定を確認し、これらの組み込み機能を利用することが最も簡単で確実な対策となります。
4. まとめ:実装の優先度
CSRF対策の優先度は以下の通りです。対策の導入時に参考にしてください。
- 必須(最優先): CSRFトークンの導入(フレームワークの利用)または SameSite Cookie属性の利用
- 併用推奨: Refererヘッダーの検証 と GETリクエストでの状態変更禁止
このセキュリティ対策を徹底することで、ユーザーが安心して利用できる堅牢なWebアプリケーションを提供できます。
コメント