CSRFとは何か

CSRF(Cross-Site Request Forgery、クロスサイトリクエストフォージェリ)とは、ユーザーが意図しない形で、ログイン中のWebアプリケーションに対して不正なリクエストを送信させる攻撃手法です。日本語では「クロスサイトリクエスト偽造」と訳されることもあります。

たとえば、あるショッピングサイトにログイン中のユーザーが、別の悪意あるWebサイトを開いたとします。このとき、悪意あるサイトに埋め込まれた仕組みによって、ショッピングサイト上で勝手に商品を購入したり、ユーザー情報を変更したりするリクエストが送られてしまう可能性があります。これは、ユーザーのログイン状態(セッション)を悪用して、利用者本人の意図とは異なる操作をWebアプリケーション側で実行させる攻撃です。

CSRFは、ユーザーの「信頼された操作」に便乗して行われるため、防御が難しい攻撃の一つとされています。

なぜCSRFが成立するのか

CSRF攻撃が成立する背景には、Webブラウザのクッキー自動送信の仕組みと、Webアプリケーションの認証処理の構造があります。

多くのWebアプリケーションでは、ユーザーのログイン状態を維持するためにセッションIDをクッキーに保存しています。ブラウザは、同じドメインに対するリクエストであれば、ユーザーが明示的に意図しない場合でも自動的にそのクッキーをサーバーに送信します。

つまり、ユーザーがログイン中である状態で第三者のWebサイトにアクセスした場合、そのWebサイトに仕掛けられたリクエストでも、ログイン中のセッション情報が付いたリクエストとして送られてしまうのです。

Webアプリケーションが「どこから送られてきたリクエストか」を確認せずに処理を実行してしまうと、このような不正リクエストが受理され、CSRF攻撃が成立してしまいます。

この「クッキーは勝手に送られる」という特性を踏まえたうえで、CSRF対策では主に「そのリクエストが正規のものであるか」を検証する仕組みを設けることが重要になります。

攻撃の仕組みと再現

CSRF攻撃がどのように行われるのか、より現代的な構成に即した例で説明します。

たとえば、ある銀行のWebアプリケーションが以下のようなPOSTリクエストにより送金処理を行っているとします。

POST https://bank.example.com/transfer
Content-Type: application/x-www-form-urlencoded

to=attacker&amount=10000

この操作は通常、銀行のWeb画面上でユーザーが送金先や金額を入力し、「送金する」ボタンを押すことで実行されます。ユーザーはすでにログイン済みであり、認証情報(セッションIDなど)はクッキーとしてブラウザに保持されています。

ここで、攻撃者が自分のWebサイト(例:https://attack.example.com)に次のようなHTMLを仕込んでおいたとします。

1
2
3
4
5
6
7
8
<form action="https://bank.example.com/transfer" method="POST" style="display: none;">
  <input type="hidden" name="to" value="attacker">
  <input type="hidden" name="amount" value="10000">
  <input type="submit">
</form>
<script>
  document.forms[0].submit();
</script>

被害者がこのページを開いた瞬間、フォームが自動で送信され、POSTリクエストが被害者のブラウザから発行されてしまいます

このとき、ブラウザは自動的にbank.example.com向けのクッキー(セッションID)を送信するため、被害者が自分で送信したかのように認証された状態でリクエストが処理されてしまうのです。

このように、攻撃者のページにアクセスするだけで、ユーザーの意図しない操作が実行されてしまうのがCSRF攻撃の本質です。

基本的なCSRF対策

1. CSRFトークンの導入

もっとも基本的かつ有効な対策が「CSRFトークン」の仕組みです。この仕組みは、セッションIDをクッキーで保持する一般的な認証方式において特に効果的です。

サーバー側の役割

  • ユーザーのセッションごとに、一意で推測困難なトークンを生成
  • トークンをサーバー側セッションに保存
  • HTMLフォームなどを通じてクライアントに提供
  • 受信したトークンとセッション保存トークンの一致を検証

クライアント側の役割

  • サーバーから提供されたトークンを取得
  • フォーム送信時などにリクエストと一緒にトークンを送信
1
2
3
<form method="POST" action="/update">
  <input type="hidden" name="csrf_token" value="abc123xyz">
</form>

このように、

  • クッキーは自動で送られる
  • トークンは明示的に送らなければならない

という非対称性を利用することで、CSRF攻撃を防ぐことができます。

2. RefererやOriginヘッダーの検証

RefererOriginヘッダーの検証も、不正なリクエストの識別に役立ちます。

  • Referer: 直前のページのURL
  • Origin: 発信元のオリジン(スキーム+ホスト+ポート)

自サイトのリクエストであれば、これらの値が一致するため、不正リクエストを検知しやすくなります。ただし、これらのヘッダーはブラウザの設定や環境によって省略されることがあるため、補助的な対策として用いるのが適切です。

3. SameSite Cookie属性の活用

クッキーにSameSite属性を設定することで、クロスサイトからのクッキー送信を制限できます。

  • Lax: 通常のGETは許容、POST等はブロック
  • Strict: クロスサイトすべて拒否
  • None; Secure: HTTPSかつクロスサイト可(Secure必須)

これにより、第三者サイトからのCSRF攻撃でクッキーが送信されなくなり、リクエストが無効化されます。

4. CORSによる制限

CORS(Cross-Origin Resource Sharing)は、クロスオリジン通信を制御する仕組みで、CSRFにも補助的に効果があります。

  • Access-Control-Allow-Originで許可オリジンを限定
  • Access-Control-Allow-Credentialsを必要な場合のみ許可

これにより、攻撃者のオリジンからの認証付きリクエストがブロックされ、CSRFを防げます。ただし、あくまで補助的な対策であり、トークン方式と併用することが推奨されます。

SPA + REST APIでのCSRF対策

SPA(Single Page Application)とREST APIの構成では、従来のWebアプリケーションとは異なるリクエストの流れや認証の仕組みが存在するため、CSRF対策にも注意が必要です。

従来の方式との違い

従来のサーバーサイドレンダリング型のアプリケーションでは、HTMLページとともにCSRFトークンをフォームに埋め込み、POSTリクエストなどでそれを送信するという手法が一般的でした。しかし、SPAでは初回にページをロードして以降、JavaScriptがクライアント上で動作し続けるため、サーバーがフォームを直接出力する機会がなく、別の方法でトークンを取得・管理する必要があります。

認証方法に応じたリスクの違い

SPAで用いられる認証手法には大きく分けて2つあります:

  • クッキーによるセッション認証
  • トークン(例:JWT)による認証

クッキー認証の場合

ブラウザは同一オリジンであればクッキーを自動送信するため、攻撃者のサイトから発生したリクエストにもセッションIDが付与されてしまいます。これは従来型アプリケーションと同様にCSRFのリスクがある構成です。

この場合は、以下のような対策を講じる必要があります:

  • CSRFトークンの運用
    • 初回ロード時にAPI(例:/csrf-token)でトークンを取得
    • JavaScriptが取得したトークンを以後のリクエストヘッダー(例:X-CSRF-Token)に付与
    • サーバー側ではヘッダーのトークンとセッションのトークンを照合
  • SameSite Cookieの設定
    • SameSite=LaxまたはStrictを指定し、クロスサイトからのリクエストに対するクッキーの自動送信を制御

トークンベース認証の場合

SPAでJWTなどのトークンをAuthorizationヘッダーに明示的に付与して認証する場合、CSRF攻撃の対象にはなりにくくなります。なぜなら、ブラウザのセキュリティ制限により、攻撃者のページから任意のHTTPヘッダーを付けたクロスオリジンのリクエストを送ることはできないためです。

このような構成では、CSRFよりもXSS(クロスサイトスクリプティング)対策が重要になります。たとえば、トークンがブラウザのローカルストレージに保存されている場合、XSSによりトークンが窃取される可能性があるためです。

実運用でのポイント

SPA + REST API構成でのCSRF対策を整理すると、以下のようになります:

  • クッキー認証を使う場合:

    • CSRFトークンの発行と検証
    • SameSite属性の設定
    • CORS設定の最小化(credentials: trueを必要最小限に)
  • トークンベース認証を使う場合:

    • CSRFの心配は基本的に不要だが、XSSへの対策を重視

どの認証方式を採用するかによって、CSRFの対策方法そのものが変わるため、構成を明確にし、必要なセキュリティ対策を整理することが重要です

まとめ

CSRF(Cross-Site Request Forgery)は、ユーザーが意図しないかたちで操作を強制される深刻な攻撃です。特に認証済みの状態が悪用されることで、本来なら許可されないはずの処理が実行されてしまいます。

この問題は、Webブラウザの仕組みとWebアプリケーションの設計の隙を突いたものであり、ユーザーの「信頼された操作」に乗じて成立します。

アプリケーションの構成や認証方式によって対策の取り方は異なりますが、CSRFという攻撃手法の構造を理解しておくことが、安全なWeb開発の土台となります。