「CSRFって何?」「XSSと何が違うの?」
Webセキュリティを学んでいると出てくるCSRF(クロスサイトリクエストフォージェリ)。名前が長くて難しそうに感じますが、仕組みを理解すれば意外とシンプルです。
この記事では、CSRFとは何か、どんな仕組みで攻撃されるのか、どう対策すればいいのかを、初心者の方にもわかりやすく解説します。
CSRF(クロスサイトリクエストフォージェリ)とは?
CSRFとは、ユーザーが意図しない操作を、そのユーザーの権限で実行させる攻撃手法です。
読み方は「シーエスアールエフ」または「シーサーフ」。言葉の意味を確認しましょう。
| 用語 | 意味 |
|---|---|
| Cross-Site | サイトをまたぐ |
| Request | リクエスト(要求) |
| Forgery | 偽造 |
つまり、「サイトをまたいでリクエストを偽造する攻撃」という意味です。
CSRFの特徴
CSRFの最大の特徴は、被害者自身の権限で操作が行われる点です。
例えば、ネットバンキングにログインしている状態で攻撃を受けると、あなた自身が送金ボタンを押したかのように不正送金が実行されてしまいます。サーバー側から見ると、正規のユーザーからの正規のリクエストに見えるため、検知が難しいのです。
CSRFの仕組みを図解
具体的にどのような仕組みで攻撃が成立するのか、ネットバンキングを例に見てみましょう。
攻撃の前提条件
CSRFが成立するには、以下の条件が必要です。
- 被害者がターゲットサイト(ネットバンキング等)にログイン中であること
- ターゲットサイトにCSRF対策が施されていないこと
- 被害者が攻撃者の用意した罠ページにアクセスすること
攻撃の流れ
- 被害者がネットバンキングにログインする
- ログイン状態を維持したまま、別のタブで攻撃者のサイトを開く
- 攻撃者のサイトには、不正なリクエストを送信する仕組みが仕込まれている
- 被害者のブラウザから、ネットバンキングに送金リクエストが自動的に送信される
- ネットバンキングは正規のリクエストと判断し、送金を実行してしまう
具体例:罠のHTMLコード
攻撃者は、以下のようなHTMLを含むページを用意します。
<!-- 見えない画像タグでGETリクエストを送信 -->
<img src="https://bank.example.com/transfer?to=attacker&amount=100000" />
<!-- または、自動送信されるフォーム -->
<form action="https://bank.example.com/transfer" method="POST" id="attack-form">
<input type="hidden" name="to" value="attacker" />
<input type="hidden" name="amount" value="100000" />
</form>
<script>
document.getElementById('attack-form').submit();
</script>
このページを開いた瞬間、被害者のブラウザから銀行サイトに対して勝手にリクエストが送信されます。
ブラウザは、同じドメイン宛のリクエストには自動的にCookieを付与します。そのため、被害者のセッション情報(ログイン状態)が一緒に送られ、銀行サイトは「正規のユーザーからのリクエスト」と判断してしまうのです。
XSSとCSRFの違い
XSSとCSRFは混同されやすいですが、攻撃の仕組みが異なります。
| 項目 | XSS | CSRF |
|---|---|---|
| 攻撃対象 | ユーザーのブラウザ | Webアプリケーション |
| 何を悪用するか | スクリプトの実行 | ユーザーの認証情報 |
| 攻撃の実行場所 | ターゲットサイト上 | 攻撃者のサイト上 |
| 主な被害 | 情報窃取、改ざん | 意図しない操作の実行 |
簡単に言うと、XSSは「悪意のあるスクリプトを実行させる」攻撃で、CSRFは「意図しないリクエストを送信させる」攻撃です。
CSRFで起こる被害
CSRF攻撃が成功すると、どのような被害が発生するのでしょうか。
1. 金銭的被害
- ネットバンキングでの不正送金
- ECサイトでの不正購入
- 有料サービスへの勝手な課金
2. アカウント情報の変更
- パスワードの変更
- メールアドレスの変更
- アカウントの乗っ取り
3. データの改ざん・削除
- 掲示板への勝手な投稿
- プロフィール情報の改ざん
- データの削除
4. 信用失墜
- SNSでの不適切な投稿
- なりすましによる誹謗中傷
実際の被害事例
CSRFによる被害は、国内外で報告されています。
- SNSサイト:ログイン中のユーザーが罠サイトを閲覧すると、勝手に投稿やフォローが行われる
- Webメール:メール転送設定を勝手に変更され、メールが攻撃者に転送される
- ルーター管理画面:DNS設定を改ざんされ、フィッシングサイトに誘導される
CASUAL TALK
服装自由・オンライン対応
まずは気軽に話しませんか?
応募じゃなくてOK。「ちょっと話を聞いてみたい」だけでも大歓迎。30分のカジュアル面談で、あなたの可能性が見えてきます。
カジュアル面談を予約するCSRFの対策方法
CSRFを防ぐための主な対策方法を紹介します。
1. CSRFトークンを使用する(最重要)
最も効果的な対策が、CSRFトークンの使用です。
CSRFトークンとは、サーバーが発行するランダムな文字列のこと。このトークンをフォームに埋め込み、リクエスト時に検証することで、正規のフォームからのリクエストかどうかを判別できます。
仕組み
- サーバーがページ表示時にランダムなトークンを生成
- トークンをフォームのhidden項目に埋め込む
- 同時にセッションにもトークンを保存
- フォーム送信時、サーバーはフォームのトークンとセッションのトークンを比較
- 一致すれば正規のリクエスト、不一致なら不正なリクエストとして拒否
HTMLの例:
<form action="/transfer" method="POST">
<input type="hidden" name="csrf_token" value="a8f3k2j4l5m6n7o8p9" />
<input type="text" name="to" />
<input type="number" name="amount" />
<button type="submit">送金</button>
</form>
攻撃者は被害者のセッションに保存されたトークンを知ることができないため、正しいトークンを含むリクエストを偽造できません。
2. SameSite属性を設定する
CookieにSameSite属性を設定すると、異なるサイトからのリクエスト時にCookieを送信しないようにできます。
Set-Cookie: session_id=abc123; SameSite=Strict
| 値 | 動作 |
|---|---|
| Strict | 異なるサイトからのリクエストには一切Cookieを送信しない |
| Lax | GETリクエストのみ送信(POSTは送信しない) |
| None | 常に送信(Secure属性が必須) |
3. Refererヘッダーの検証
リクエストのRefererヘッダー(どのページから来たか)を検証し、自サイト以外からのリクエストを拒否する方法です。
ただし、Refererはユーザーの設定で送信されないこともあるため、補助的な対策として使用します。
4. 重要な操作には再認証を要求する
送金やパスワード変更などの重要な操作では、パスワードの再入力を求めることで、CSRF攻撃を防げます。
5. フレームワークの機能を使う
多くのWebフレームワーク(Laravel、Rails、Djangoなど)には、CSRF対策機能が標準で備わっています。
Laravelの例:
<form action="/transfer" method="POST">
@csrf <!-- 自動的にCSRFトークンが埋め込まれる -->
...
</form>
まとめ
この記事で解説した内容をまとめます。
| 項目 | 内容 |
|---|---|
| CSRFとは | ユーザーが意図しない操作を、そのユーザーの権限で実行させる攻撃 |
| 攻撃の条件 | ユーザーがログイン中、CSRF対策なし、罠ページへのアクセス |
| 主な被害 | 不正送金、アカウント変更、データ改ざん、なりすまし |
| 最も重要な対策 | CSRFトークンの使用 |
| その他の対策 | SameSite属性、Referer検証、再認証、フレームワーク活用 |
CSRFは、ユーザー自身の操作に見せかけて不正を働くため、非常に危険な攻撃です。フォームを作成する際は、必ずCSRFトークンを実装しましょう。フレームワークを使えば、ほとんど自動で対策できます。
CASUAL TALK
服装自由・オンライン対応
まずは気軽に話しませんか?
応募じゃなくてOK。「ちょっと話を聞いてみたい」だけでも大歓迎。30分のカジュアル面談で、あなたの可能性が見えてきます。
カジュアル面談を予約する