CSRF攻撃のリスクと被害事例|Webセキュリティの基礎と対策をわかりやすく解説
新人
「先輩、CSRF攻撃って聞いたことあるんですが、どういうものなんですか?」
先輩
「CSRF攻撃は、ユーザーが意図しない操作を第三者にさせられてしまう、Webセキュリティ上の危険な攻撃手法だよ。」
新人
「ユーザーが勝手に操作されるって、どういうことですか?」
先輩
「たとえば、ログインしたままの状態で悪意のあるWebサイトを開くと、自分が意図してないのにフォームが勝手に送信されちゃうってことがあるんだ。」
新人
「えっ、それってすごく危ないですね……」
先輩
「うん、だからCSRF攻撃は非常に重要なリスクとして扱われているよ。では、まずはその仕組みから見ていこう!」
1. CSRF攻撃とは?
CSRF攻撃(クロスサイト・リクエスト・フォージェリ)は、ユーザーが意図しないリクエストをWebアプリケーションに送信させる攻撃手法です。特に、ログイン中のセッションを悪用されてしまうケースが多く、被害が深刻化しやすいのが特徴です。
例えば、銀行のWebサイトにログインした状態で、悪意あるサイトを開いたとします。そこには次のようなフォームが自動送信されるスクリプトが仕込まれているとします。
<form action="https://example-bank.com/transfer" method="POST">
<input type="hidden" name="toAccount" value="12345678">
<input type="hidden" name="amount" value="10000">
<input type="submit" value="送金">
</form>
<script>
document.forms[0].submit();
</script>
このようなHTMLがユーザーのブラウザ上で自動的に実行されてしまうと、本人の意思とは関係なく送金が実行される可能性があります。これが、CSRF(Cross-Site Request Forgery)攻撃の典型的な例です。
2. なぜCSRFが問題になるのか
CSRF攻撃が問題視される最大の理由は、「本人の認証情報が使われたリクエストに見える」点にあります。たとえば、ユーザーがログイン済みの場合、そのセッション情報(Cookieなど)は自動的に付与されてしまうため、サーバ側では「正当なリクエスト」として処理してしまいます。
そのため、以下のような操作が悪用されるリスクがあります。
- ユーザーのパスワード変更
- 登録済みメールアドレスの変更
- 商品購入の確定処理
- 送金や振込の実行
これらはすべて「ログイン中のセッションを悪用されたリクエスト」によって実行される可能性があり、本人は気づかないまま被害を受けることになります。
また、セキュリティ上の観点から、POSTリクエストだけでなく、GETリクエストでもCSRF対策が必要になる場合があります。以下のように、Javaでは通常のフォームから送信される内容は以下のようになります。
<form action="/updateEmail" method="POST">
<input type="email" name="email" value="test@example.com">
<input type="submit" value="変更">
</form>
このフォームが、悪意あるサイトで自動送信されてしまうと、本来の利用者が気づかないうちにメールアドレスが変更されるなどの事態が起きてしまいます。
このように、CSRF攻撃は非常に身近なリスクでありながら、気づきにくいため対策が重要なのです。
3. 実際に起きたCSRF攻撃の被害事例
ここでは、実際に発生したCSRF攻撃の事例や、それに近い想定事例をもとに、初心者にもわかりやすくリスクを解説します。CSRF攻撃事例を理解することは、Webアプリの脆弱性を意識する第一歩です。
国内ショッピングサイトでの被害事例(※想定ベース)
あるECサイトで、ユーザーがログインした状態で以下のようなマイページ画面が存在していたとします。
- パスワード変更フォーム
- クレジットカード情報更新フォーム
- アドレス帳の編集ページ
このサイトではCSRFトークンの実装がされておらず、リクエスト送信元の確認もされていませんでした。攻撃者は次のようなHTMLを作成し、メールや掲示板などを通じてターゲットにクリックさせるよう誘導します。
<form action="https://shop.example.com/changePassword" method="POST">
<input type="hidden" name="newPassword" value="hacked123">
<input type="submit" value="変更">
</form>
<script>
document.forms[0].submit();
</script>
ユーザーがリンクをクリックしてしまうと、ログイン済みセッションのままパスワードが勝手に書き換えられてしまい、不正ログインやアカウント乗っ取りのリスクが発生します。
海外SNSサービスでのCSRF攻撃(実例)
かつて海外の有名SNSサービスで、CSRF攻撃によってステータス投稿が勝手に実行される被害が発生しました。ユーザーがあるニュースサイトを閲覧しているだけで、SNSの投稿欄に「このニュースは最高だ!」といった内容が自動投稿されてしまったのです。
この攻撃は、以下のようなステップで実行されました。
- SNSにログインした状態で、別の悪意あるWebページを開く
- そのページに隠されたフォームが存在
- JavaScriptにより自動送信され、SNSに投稿されてしまう
この被害は数千人規模で発生し、大きなセキュリティ事故として話題になりました。CSRF攻撃の脅威が現実のものだと証明された事例です。
4. CSRF攻撃が発生する典型的なパターン
CSRF攻撃には共通したいくつかのパターンがあります。これを理解することで、Webアプリの脆弱性に早めに気づき、事前に対策を打つことができます。
パターン①:HTMLフォーム送信の悪用
攻撃者は、ターゲットサイトと同じ構造のHTMLフォームを外部のWebページに埋め込みます。そして、以下のようなスクリプトで自動送信させます。
<form action="https://target-site.com/account/delete" method="POST">
<input type="hidden" name="confirm" value="true">
<input type="submit" value="削除">
</form>
<script>
document.forms[0].submit();
</script>
このようなコードは、見た目には何も表示されず、裏側で勝手に送信されてしまうため、ユーザーは気づくことができません。
パターン②:画像タグなどを使ったGETリクエスト型
POSTだけでなく、GETリクエストでもCSRFは発生します。例えば以下のように、画像タグを悪用した攻撃も存在します。
<img src="https://bank.example.com/transfer?to=999999&amount=10000">
この画像タグが読み込まれると、ユーザーのセッションが生きている状態で銀行サイトにリクエストが送られ、意図しない送金が行われてしまう危険性があります。
パターン③:JavaScriptを使わないシンプルなリンク
以下のようなリンクを踏むだけで、攻撃が成立する場合もあります。
<a href="https://target.example.com/changeEmail?email=hacker@example.com">ここをクリック</a>
ユーザーがうっかりこのリンクをクリックすると、ログイン中のセッションを使って攻撃が成立します。このように、CSRF攻撃はJavaScriptを使わなくても成立することがあり、より対策が難しくなっています。
CSRF攻撃が成立する条件とは?
以下の条件がすべて揃ったとき、CSRF攻撃は成立しやすくなります。
- ユーザーがターゲットサイトにログイン済みである
- ターゲットサイトにCSRFトークンなどの防御策がない
- 攻撃者がリクエストの内容を事前に知っている、または予測できる
これらの条件を少しでも崩すことで、CSRFの成功率を下げることができます。
セキュリティ事故を防ぐ意識が重要
CSRF攻撃事例や典型的な攻撃パターンを知ることは、Webアプリのセキュリティ設計において極めて重要です。特に、JavaとSpringを使ってWebアプリを構築する際には、CSRF対策の初期設定をしっかりと行う必要があります。
次のセクションでは、実際にSpring SecurityでCSRF対策を行う方法について、設定例を交えて解説していきます。
5. 被害を防ぐために必要な考え方と開発時の注意点
CSRF攻撃を防ぐためには、単にライブラリの設定を行うだけでなく、開発者自身が「Webアプリケーションは常に攻撃対象となる可能性がある」という意識を持つことが重要です。特に、Spring Frameworkでの開発では、セキュリティの基本方針を理解しておくことで、設計段階から強固なアプリケーションを作ることができます。
まず、設計時点で「CSRFによる不正なリクエストが入ってくる可能性がある」という前提で、機能を実装しましょう。たとえば以下のような処理は、特に慎重に対策を検討すべきです。
- アカウント情報の変更(パスワード・メールアドレスなど)
- 注文や申請処理
- 送金やポイント交換など金銭が関係する操作
次に、サーバー側では「信頼できるリクエストかどうか」を判別できるような仕組みが必要です。その代表的な方法が「CSRFトークン」を用いる対策です。
CSRFトークンとは、フォームを表示する際に生成された一意のトークンを、フォーム送信時に一緒に送信し、サーバー側で照合するという仕組みです。これにより、悪意のあるサイトから自動送信されたフォームには正しいトークンが含まれていないため、不正なリクエストを検知してブロックできます。
また、開発時に注意すべきポイントとして、以下が挙げられます。
- セキュリティ設定を明示的に記述すること(デフォルト任せにしない)
- 意図しないGETリクエストでも更新系の処理を行わない
- JavaScriptで勝手に送れるようなAPI設計にしない
- テンプレートにCSRFトークンを必ず埋め込む
このように、セキュリティを考慮したコーディングと設計がCSRF攻撃の防止につながります。
6. Spring SecurityでCSRF対策を有効にする基本設定
Spring Securityでは、CSRF対策は標準で有効になっているため、明示的に無効化しない限り基本的な保護が働いています。しかし、設定ファイルでの確認とトークン埋め込みの処理をしっかり行うことで、より堅牢なセキュリティ対策が実現できます。
Spring SecurityのJava Configでの設定
まず、セキュリティ設定クラスにおいて、明示的にCSRFを有効化し、フォームベースの認証も設定します。
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf() // CSRF対策を有効化(デフォルトだが明示しておく)
.and()
.authorizeRequests()
.antMatchers("/login", "/error").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("/home", true)
.permitAll();
}
}
この設定では、Spring SecurityのCSRF対策が有効になった状態で、ログインフォームからの認証や、認証後のアクセス制御を行っています。
HTMLフォームへのCSRFトークンの埋め込み
Spring MVCの@Controllerを使用する場合、ThymeleafやJSPなどのテンプレート上にCSRFトークンを埋め込む必要があります。以下はJSPでCSRFトークンを含める例です。
<form action="/updateProfile" method="POST">
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}">
<input type="text" name="username" value="testuser">
<input type="submit" value="更新">
</form>
上記のように、Spring Securityは自動的に_csrfという属性をモデルに追加してくれます。これを利用してCSRFトークンをフォーム内に埋め込むことが可能です。
CSRFトークンがない場合の挙動
CSRFトークンが不足している、または不一致の場合、Spring SecurityはHTTPステータス403(Forbidden)を返して処理を中断します。これにより、不正なリクエストをブロックすることができます。
CSRF対策が不要なケースの除外設定(例外)
一部のエンドポイント(例:APIやWebhookなど)ではCSRF対策が不要な場合もあります。その場合は、以下のように除外設定を行うことが可能です。
http
.csrf()
.ignoringAntMatchers("/api/**");
ただし、APIにも認証情報が必要な場合は、別途トークン認証やOAuth2などの導入が推奨されます。
開発環境での注意点
Pleiadesを使ってSpringプロジェクトを構築する場合、依存関係にspring-boot-starter-securityが含まれていれば、自動的にCSRF対策が有効になります。ただし、HTMLテンプレート側でトークン埋め込みを忘れると、POST送信時に403エラーとなるため、開発初期から意識して実装しましょう。
このように、Spring Security CSRF対策は、正しく設定することで効果的にセキュリティ事故を防ぐことができます。Webアプリの脆弱性を回避し、安全なサービスを提供するためにも、開発者が最初に押さえておくべき大切なポイントといえます。