CSRF(クロスサイトリクエストフォージェリ)とは?仕組みから対策まで徹底解説

Webサイトを運営していると、セキュリティの脅威は日々進化しています。その中でも、ユーザー本人が気づかないうちに不正な操作を実行させられてしまうCSRF攻撃は、特に注意が必要な脆弱性の一つです。

本記事では、CSRFの仕組みから実際の被害事例、そして効果的な対策方法まで、セキュリティの専門家の視点を交えながら詳しく解説していきます。

XSSとの違いや、実装時の落とし穴についても触れていくため、開発者の方にも役立つ内容となっています。

CSRFとは何か

CSRF(Cross-Site Request Forgery)は、クロスサイトリクエストフォージェリの略称で、日本語では「リクエスト強要」とも呼ばれます。別名として「XSRF」や「Session Riding(セッションライディング)」という呼び方もありますが、いずれも同じ脆弱性を指しています。

この攻撃の本質は、Webサイトの利用者が意図しない処理を勝手に実行させられてしまう点にあります。攻撃者は利用者のログイン状態を悪用し、まるで本人が操作しているかのように見せかけて不正な処理を実行させるのです。

CSRFが発生する背景と条件

では、なぜこのような攻撃が可能になるのでしょうか。その背景には、Webアプリケーションの認証の仕組みが深く関わっています。

多くのWebサービスでは、ログイン時にセッションIDやCookieを発行し、それ以降のリクエストではこの情報を使って「この人は正規のユーザーだ」と判断しています。ところが、ブラウザは同じドメインへのリクエストに対して、自動的にCookieを送信してしまうという特性があります。

攻撃者はこの特性を巧みに利用します。利用者が正規サイトにログイン中の状態で、攻撃者が用意した罠サイトにアクセスさせることで、利用者のブラウザから正規サイトに対して自動的にリクエストを送信させるのです。

CSRF攻撃が成立するには、いくつかの条件が揃う必要があります。


  1. 利用者が標的となるWebサイトにログインしている状態であること



  2. 攻撃者が、標的サイトでどのような処理をするためにどんなパラメータが必要かを把握していること



  3. その処理が、外部サイトからのリクエストを区別せずに受け付けていること


特に3つ目の条件は重要です。外部サイトからの不正なリクエストと、正規のページからのリクエストを区別できていないことが、この脆弱性の根本原因となっています。

攻撃が成功しやすいサイトの特徴

実務の現場では、以下のような特徴を持つサイトがCSRF攻撃のターゲットになりやすいことがわかっています。

GETメソッドで重要な処理を実行しているサイトは、最も危険度が高いといえます。本来、GETメソッドは情報の取得に使うべきものであり、データの更新や削除といった副作用のある処理には適していません。しかし、開発の現場では実装の簡便さから、URLにパラメータを付けるだけで処理が実行できるGETメソッドを使ってしまうケースが少なくありません。

金融取引や個人情報の変更といった機密性の高い処理を扱うサイトも、当然ながら攻撃者の標的となりやすくなります。オンラインバンキング、ECサイト、会員制サービスなどは特に注意が必要です。

意外と見落とされがちなのが、ログアウト機能にCSRF脆弱性が存在するケースです。ログアウト自体は機密情報を扱わないため軽視されることもありますが、これを悪用されると利用者のセッションが勝手に切断され、その後の攻撃の足がかりにされる可能性があります。

CSRF攻撃の仕組みと手法

ここからは、CSRF攻撃が実際にどのように行われるのか、その具体的な手法を見ていきましょう。

典型的な攻撃の流れ

CSRF攻撃は、一般的に以下のようなステップで実行されます。

まず、利用者が正規のWebサイト(例えばオンラインバンキング)にログインします。この時点で、ブラウザにはセッション管理用のCookieが保存された状態になっています。

次に、利用者が何らかの形で攻撃者の用意した罠サイトにアクセスします。メールのリンクをクリックしたり、SNSで共有された悪意のあるURLを踏んだりするケースが多いでしょう。

罠サイトには、利用者のブラウザから正規サイトへ自動的にリクエストを送信する仕掛けが埋め込まれています。HTMLのimgタグやiframeタグ、JavaScriptなどを使って、ページが読み込まれた瞬間にリクエストが発生するようになっているのです。

ブラウザは、罠サイトから指示された通りに正規サイトへリクエストを送信します。この時、正規サイトのCookieが自動的に付与されるため、サーバー側からは正規の利用者からのリクエストに見えてしまいます。

最終的に、サーバーは「これは正規ユーザーからのリクエストだ」と判断して処理を実行してしまい、送金や個人情報の変更といった重要な操作が勝手に行われてしまうのです。

GETメソッドを悪用した攻撃パターン

GETメソッドを使った攻撃は、最もシンプルで実装しやすい手法です。攻撃者は、以下のようなHTMLコードを罠サイトに仕込むだけで攻撃が可能になります。

<img src="https://example-bank.com/transfer?to=attacker&amount=100000" width="0" height="0">

このimgタグは、見た目には何も表示されませんが、ブラウザは指定されたURLに対してGETリクエストを送信しようとします。もし利用者がexample-bank.comにログイン中であれば、このリクエストには自動的にセッションCookieが付与され、送金処理が実行されてしまう可能性があるのです。

実際の攻撃では、画像だけでなくCSSの背景画像指定やJavaScriptのfetch APIなど、さまざまな方法でGETリクエストを発生させることができます。開発者がGETメソッドで状態変更の処理を実装してしまうと、このような単純な手法だけでも重大な被害につながってしまいます。

POSTメソッドを悪用した攻撃パターン

GETメソッドの危険性が広く認知されたことで、多くのサイトではPOSTメソッドを使うようになりました。しかし、POSTメソッドを使っているだけではCSRF対策として不十分です。

POSTリクエストを発生させるには、少し工夫が必要になります。攻撃者は、罠サイトに自動送信されるフォームを埋め込みます。

<body onload="document.forms[0].submit()">
<form action="https://example-bank.com/transfer" method="POST">
  <input type="hidden" name="to" value="attacker">
  <input type="hidden" name="amount" value="100000">
</form>
</body>

このコードでは、ページが読み込まれると同時に(onloadイベントで)フォームが自動送信されます。利用者は何も操作していないのに、バックグラウンドでPOSTリクエストが正規サイトに送信されてしまうのです。

より巧妙な攻撃者は、JavaScriptを使ってAjaxリクエストを発生させたり、クリックジャッキングと組み合わせて利用者に気づかれないようボタンをクリックさせたりといった手法を使うこともあります。

フィッシング詐欺との違い

CSRF攻撃とフィッシング詐欺は、しばしば混同されることがありますが、その手法と目的は大きく異なります。

フィッシング詐欺は、偽のWebサイトを作成して利用者のログイン情報を直接盗み取る手法です。本物そっくりの偽サイトに誘導し、そこでIDやパスワードを入力させることで認証情報を窃取します。

一方、CSRF攻撃では、攻撃者は利用者のログイン情報を直接盗む必要がありません。既に正規サイトにログインしている利用者のブラウザを悪用して、正規サイト上で不正な処理を実行させるのです。

つまり、フィッシングは「認証情報を盗んでから攻撃者が操作する」のに対し、CSRFは「利用者のブラウザに操作させる」という違いがあります。攻撃者の視点から見ると、CSRFの方が実装が容易で、利用者に気づかれにくいという特徴があります。

XSSとの違いと関係性

セキュリティの議論では、CSRFと並んでXSS(クロスサイトスクリプティング)という脆弱性もよく取り上げられます。両者は名前も似ており、混同されやすいのですが、攻撃の性質は大きく異なります。

攻撃の主体と目的の違い

XSSは、攻撃者が用意した悪意のあるスクリプトを、正規サイト上で実行させる攻撃です。利用者が入力したデータを適切にサニタイズせずに表示してしまうサイトに対して、JavaScriptコードを注入し、そのスクリプトが他の利用者のブラウザ上で実行されるようにします。

XSSの主な目的は、Cookieの窃取、セッションハイジャック、画面の改ざん、キー入力の監視など、正規サイト内で自由にJavaScriptを実行できることを悪用した攻撃です。

一方、CSRFは先ほど説明した通り、利用者のブラウザから正規サイトに対してリクエストを送信させる攻撃です。攻撃者のスクリプトは罠サイト上で実行され、そこから正規サイトに対してHTTPリクエストを発生させます。

この違いを整理すると、XSSは「正規サイト内でスクリプトを動かす」攻撃であり、CSRFは「外部から正規サイトにリクエストを送る」攻撃といえます。

XSS脆弱性が引き起こす複合的なリスク

ここで注意すべきは、XSSとCSRFは組み合わさることで、より深刻な被害をもたらすという点です。

多くのCSRF対策は、トークンを使った仕組みに依存しています。処理を実行する際に、予測不可能なランダム値(CSRFトークン)を要求することで、外部サイトからのリクエストを弾くという方法です。

しかし、サイトにXSS脆弱性が存在すると、攻撃者は正規サイト上でJavaScriptを実行できてしまうため、CSRFトークンの値を取得することが可能になります。正規ページのHTMLからトークンを読み取り、それを使って不正なリクエストを構築できてしまうのです。

実際のセキュリティ診断の現場では、XSSとCSRFの両方の脆弱性が存在するサイトに遭遇することがあります。このようなサイトでは、CSRF対策が実装されていても、XSS脆弱性を踏み台にしてCSRF攻撃が成功してしまうケースが報告されています。

そのため、CSRF対策だけでなく、XSS対策も並行して実施することが重要です。一方の対策だけでは不十分であり、多層的なセキュリティアプローチが求められます。

CSRF攻撃による被害とリスク

CSRF攻撃が成功すると、どのような被害が発生するのでしょうか。利用者側とサービス提供者側、それぞれの視点から見ていきましょう。

利用者に発生する直接的な被害

最も深刻なケースは、金銭的な被害です。オンラインバンキングやクレジットカード決済サイトでCSRF攻撃が成功すると、利用者の意図しない送金や購入が実行されてしまいます。

ある国内の銀行では、過去にCSRF脆弱性を突かれ、ログイン中の利用者が知らないうちに振込処理を実行させられる事件が発生しました。利用者は自分が操作した覚えがないため、気づいた時には既に送金が完了しており、資金の回収が困難になっていたケースもあります。

ECサイトでは、勝手に商品を購入させられる被害が報告されています。攻撃者は自身が欲しい商品を、被害者のアカウントで購入させ、配送先を攻撃者の住所に設定するといった手口を使います。

SNSやブログサービスでは、意図しない投稿や情報発信をさせられる被害があります。利用者になりすまして不適切な内容を投稿させることで、その人の評判を傷つけたり、スパムを拡散させたりといった目的で悪用されます。

会員情報の変更も標的になります。メールアドレスやパスワードを勝手に変更されると、アカウントへのアクセス権を失う可能性があります。特にメールアドレスを変更されてしまうと、パスワードリセット機能も使えなくなり、アカウントの奪取につながる危険性があります。

サービス提供者側に及ぶ影響

CSRF攻撃は、サービスを提供する企業側にも大きな影響を与えます。

まず考えられるのは、信頼性の低下とブランドイメージの毀損です。利用者が不正な処理の被害に遭った場合、たとえサイト側に脆弱性があったとしても、利用者からすれば「このサービスは危険だ」という印象を持たれてしまいます。

セキュリティインシデントが公になれば、メディアで報道され、SNSで拡散されることで、企業の評判は大きく傷つきます。一度失った信頼を取り戻すには、長い時間とコストがかかります。

法的責任も問われる可能性があります。個人情報保護法では、事業者に適切な安全管理措置を講じる義務が定められており、脆弱性を放置していたことが過失と判断されるケースもあります。

被害者から損害賠償を請求される場合、その対応にかかる法務コストや賠償金は、特に中小企業にとっては経営を揺るがすほどの負担となり得ます。

さらに、インシデント対応には多くのリソースが必要です。被害状況の調査、システムの緊急修正、利用者への説明と謝罪、再発防止策の策定など、通常業務に加えて膨大な作業が発生します。

開発チームは本来予定していた機能開発を中断し、セキュリティ対応に追われることになります。このような機会損失も、見えにくいコストとして企業に影響を与えます。

実際に発生した被害事例

国内では、いくつかの著名な事例が報告されています。

2005年に発生した「ぼくはまちちゃん騒動」は、CSRF攻撃の典型例として語り継がれています。大手掲示板サイトにおいて、CSRF脆弱性を悪用して他人のアカウントで勝手に投稿させる攻撃が行われました。

この事件では、罠サイトに誘導された利用者が、知らないうちに掲示板に「ぼくはまちちゃん」という投稿をさせられる被害が多発しました。攻撃者は、被害の拡大を可視化するために、あえて目立つ定型文を投稿させていたと考えられています。

2008年の横浜市小学校襲撃予告事件も、CSRF攻撃が関与した重大な事例です。この事件では、掲示板のCSRF脆弱性を悪用して、無関係の人物に犯行予告の書き込みをさせるという手口が使われました。

被害者は突然警察の捜査を受けることになり、容疑が晴れるまでに大きな精神的苦痛を受けました。この事件は、CSRF攻撃が単なる金銭被害にとどまらず、刑事事件に巻き込まれるリスクがあることを社会に示しました。

2012年には、EC-CUBEという国内で広く使われているECサイト構築システムにおいて、CSRF脆弱性が発見されました。この脆弱性を悪用されると、管理者が意図しない商品情報の変更や、顧客情報の漏洩につながる可能性がありました。

EC-CUBEは多くの企業で採用されていたため、この脆弱性の影響範囲は広く、緊急のセキュリティアップデートが実施されました。オープンソースソフトウェアであっても、適切な脆弱性管理が必要であることを示す事例となりました。

利用者側ができるCSRF対策

ここまで見てきた通り、CSRF攻撃は主にサービス提供者側の脆弱性に起因します。しかし、利用者側でも注意することで、被害のリスクを軽減することが可能です。

ログイン状態の適切な管理

最も基本的かつ効果的な対策は、重要なサービスを使い終わったら必ずログアウトすることです。

多くの人は、利便性を優先してブラウザにログイン状態を保存したままにしがちです。特にスマートフォンのアプリでは、一度ログインすると半永久的にログイン状態が維持されることもあります。

しかし、ログインしたままの状態でいると、その間ずっとCSRF攻撃のリスクにさらされることになります。特にオンラインバンキングやクレジットカードサイトなど、金銭に関わるサービスは使用後すぐにログアウトする習慣をつけましょう。

複数のサービスに同時ログインしている状態も危険です。例えば、SNSとオンラインバンキングの両方にログインしたまま、怪しいリンクをクリックしてしまうと、どちらのサービスでも不正な操作をされる可能性があります。

ブラウザのプライベートブラウジングモード(シークレットモード)を活用するのも有効です。このモードでは、ウィンドウを閉じると自動的にCookieやセッション情報が削除されるため、ログアウトし忘れのリスクを減らせます。

不審なリンクへのアクセス回避

CSRF攻撃の多くは、利用者を罠サイトに誘導することから始まります。そのため、不審なリンクをクリックしないという基本的な注意が重要になります。

メールで送られてくるリンクは、特に注意が必要です。たとえ知人からのメールに見えても、そのアカウントが乗っ取られている可能性があります。メール本文の日本語が不自然だったり、普段と違う文体だったりする場合は、リンクをクリックする前に別の方法で本人に確認しましょう。

SNSで拡散されているリンクも要注意です。「このリンクをクリックすると面白いことが起きます」といった煽り文句で、好奇心を刺激して罠サイトに誘導するケースが多く見られます。

短縮URLサービスを使ったリンクは、実際のURLが隠されているため、リンク先の安全性を判断することが困難です。信頼できない送信元からの短縮URLは、できるだけ避けた方が賢明でしょう。

ブラウザのブックマーク機能を活用することも推奨されます。重要なサービスにアクセスする際は、メールやSNSのリンクではなく、自分でブックマークしたURLから直接アクセスする習慣をつけると、フィッシングサイトへの誘導も防げます。

異常な動作への気づきと対応

自分のアカウントで身に覚えのない操作が行われていないか、定期的に確認することも大切です。

オンラインバンキングでは、取引履歴を頻繁にチェックしましょう。見覚えのない送金や引き落としがあれば、すぐに金融機関に連絡してください。早期発見できれば、被害の拡大を防いだり、資金を回復できる可能性が高まります。

ECサイトでは、注文履歴や配送先住所の確認が重要です。勝手に商品が購入されていたり、知らない住所が登録されていたりする場合、すぐにサイト運営者に報告しましょう。

SNSやブログでは、自分が投稿していない内容がないかチェックします。特に、不適切な内容やスパム的な投稿が自分のアカウントから発信されている場合、CSRF攻撃を受けている可能性があります。

メールアドレスやパスワードの変更通知メールが届いたのに、自分で変更した覚えがない場合も、すぐに対応が必要です。アカウントの乗っ取りが進行している可能性があるため、緊急でパスワードを変更し、サービス提供者に連絡しましょう。

多くのサービスでは、ログイン履歴やアクセスログを確認できる機能が提供されています。定期的にこれらをチェックし、見覚えのない場所やデバイスからのアクセスがないか確認することで、不正アクセスの早期発見につながります。

サービス提供者側の根本的な対策

ここからは、Webサービスを開発・運営する立場の方向けに、CSRF攻撃を防ぐための技術的な対策を解説していきます。

CSRFトークンの実装

最も効果的で広く採用されているのが、CSRFトークン(ワンタイムトークン)を使った対策です。

この手法の基本的な考え方は、フォームに予測不可能なランダムな値を埋め込んでおき、リクエストを受け取った際にその値が正しいかどうかを検証するというものです。

具体的な実装の流れを見てみましょう。まず、フォームを表示する際に、サーバー側でランダムなトークンを生成します。このトークンは、セッション情報に保存すると同時に、HTMLフォームのhiddenフィールドに埋め込まれます。

<form action="/transfer" method="POST">
  <input type="hidden" name="csrf_token" value="ランダムに生成された値">
  <input type="text" name="amount">
  <button type="submit">送金</button>
</form>

利用者がフォームを送信すると、このhiddenフィールドの値も一緒にサーバーに送られます。サーバー側では、受け取ったトークンの値と、セッションに保存しておいた値が一致するかを確認します。

一致すれば正規のリクエストと判断して処理を実行し、一致しなければリクエストを拒否します。外部サイトからのリクエストには、正しいトークン値を含めることができないため、CSRF攻撃を防ぐことができるのです。

トークンの生成には、暗号学的に安全な乱数生成器を使用することが重要です。単純な乱数や、予測可能なパターンを使うと、攻撃者にトークン値を推測されてしまう危険性があります。

多くのWebフレームワークでは、CSRF対策の機能が標準で提供されています。例えば、Ruby on RailsではデフォルトでCSRFトークンが有効になっており、開発者が特別な実装をしなくても基本的な対策ができるようになっています。

DjangoやLaravelといった他のフレームワークでも、同様の機能が用意されています。これらを活用することで、実装の負担を減らしつつ、確実な対策が可能です。

ただし、フレームワークの機能を使う際も、その動作原理を理解しておくことは重要です。例えば、Ajaxリクエストを使う場合は、トークンをHTTPヘッダーに含める必要があるなど、通常のフォーム送信とは異なる実装が求められることもあります。

Refererヘッダの検証

もう一つの有効な対策が、Refererヘッダを検証する方法です。

RefererヘッダとはHTTPリクエストに含まれる情報で、「このリクエストはどのページから送信されたか」を示します。正規のフォームから送信されたリクエストであれば、Refererには自サイトのURLが含まれているはずです。

サーバー側で、Refererヘッダの値をチェックし、自サイトのドメインから始まっているかを確認します。外部サイトからのリクエストであれば、Refererには罠サイトのURLが含まれているため、不正なリクエストとして弾くことができます。

この方法のメリットは、実装が比較的簡単な点です。トークンの生成や管理が不要で、リクエストを受け取った時点でRefererをチェックするだけで済みます。

しかし、いくつかの注意点もあります。まず、Refererヘッダは必ずしも送信されるとは限りません。プライバシー保護の観点から、ブラウザやセキュリティソフトがRefererの送信をブロックしている場合があります。

そのため、Refererが存在しないリクエストをすべて拒否してしまうと、正規の利用者を締め出してしまう可能性があります。実装時には、Refererが空の場合の扱いについて慎重に検討する必要があります。

また、HTTPSからHTTPへのリクエストでは、セキュリティ上の理由でRefererが送信されないケースもあります。サイト全体をHTTPS化していれば問題ありませんが、混在環境では注意が必要です。

Refererの検証は、CSRFトークンと併用することで、より強固な防御を実現できます。トークンによる検証をメインとしつつ、Refererチェックを追加の防御層として実装するのが理想的です。

SameSite Cookie属性の活用

比較的新しい対策手法として、CookieのSameSite属性を使う方法があります。

SameSite属性を設定すると、クロスサイトリクエストの際にCookieを送信するかどうかをブラウザ側で制御できるようになります。つまり、外部サイトから自サイトへのリクエストには、自動的にCookieを付与しないようにできるのです。

SameSite属性には、Strict、Lax、Noneという3つの設定値があります。

Strictに設定すると、クロスサイトリクエストでは一切Cookieが送信されなくなります。最も厳格な設定ですが、外部サイトのリンクから自サイトにアクセスした場合でもログイン状態が維持されないため、利便性が大きく損なわれます。

Laxは、GETメソッドの通常のナビゲーション(リンククリック)では Cookieが送信されますが、POSTリクエストやimgタグなどからのリクエストでは送信されない設定です。CSRF対策としては十分な効果があり、かつ利便性への影響も少ないため、多くのケースで推奨される設定となっています。

Noneは、従来通りすべてのリクエストでCookieを送信する設定です。ただし、Noneを指定する場合はSecure属性(HTTPS通信でのみ送信)も同時に設定する必要があります。

近年のブラウザでは、SameSite属性が明示的に指定されていない場合、デフォルトでLaxとして扱われるようになってきています。これにより、開発者が特別な対応をしなくても、ある程度のCSRF対策が自動的に適用されるようになりました。

ただし、SameSite属性はブラウザの実装に依存するため、古いブラウザでは機能しません。また、正当なクロスサイトの用途(例えば、決済代行サービスとの連携)では、意図しない動作を引き起こす可能性もあります。

そのため、SameSite属性は補助的な対策として位置づけ、CSRFトークンなどの他の対策と組み合わせて使用することが推奨されます。

パスワード再入力による確認

金銭の送金や重要な設定変更など、特に重大な処理を実行する際には、パスワードの再入力を求めることも有効な対策です。

この方法では、処理を実行する直前のページで、もう一度パスワードの入力を要求します。正しいパスワードが入力された場合のみ、処理を続行するという仕組みです。

CSRF攻撃では、攻撃者は利用者のセッションを悪用できますが、パスワードそのものは知りません。そのため、パスワード再入力を要求することで、CSRF攻撃を防ぐことができます。

ただし、この方法には利便性を損なうというデメリットがあります。頻繁にパスワード入力を求められると、利用者は煩わしさを感じ、サービスの利用体験が悪化します。

そのため、すべての処理でパスワード再入力を求めるのではなく、本当に重要な処理に限定して適用するのが現実的です。例えば、送金額が一定金額を超える場合や、メールアドレスの変更など、アカウントの安全性に直接関わる操作に限定します。

また、パスワード入力の代わりに、二要素認証(2FA)を使う方法も効果的です。SMSで送信されるワンタイムパスワードや、認証アプリで生成されるコードを入力させることで、より強固なセキュリティを実現できます。

処理実行後の通知メール

直接的な攻撃の防止ではありませんが、重要な操作が実行された際に通知メールを送信する仕組みも、被害の早期発見と拡大防止に役立ちます。

送金処理、パスワード変更、メールアドレス変更、高額商品の購入など、重要な処理が完了したら、登録されているメールアドレスに自動的に通知を送ります。

もし利用者が操作した覚えがないのに通知が届けば、すぐに異常に気づくことができます。早期に発覚すれば、被害を最小限に抑えたり、不正な処理を取り消したりといった対応が可能になります。

通知メールには、実行された処理の詳細(日時、金額、変更内容など)を記載し、心当たりがない場合の連絡先を明記しておくことが重要です。

この対策は、CSRF攻撃そのものを防ぐものではありませんが、被害の早期発見という点で非常に有効です。他の対策と組み合わせて、多層的なセキュリティ体制を構築しましょう。

対策の落とし穴と注意点

ここまで様々な対策を紹介してきましたが、実装時には思わぬ落とし穴が潜んでいることがあります。実務の現場で見られる典型的な失敗例を見ていきましょう。

トークンの管理ミス

CSRFトークンを実装したものの、トークンの検証を特定の処理でのみ行っているというケースがあります。

例えば、メインの送金処理ではトークンを検証しているのに、送金先の登録処理では検証を忘れているといった状況です。攻撃者は検証が甘い部分を狙って攻撃を仕掛けてくるため、すべての状態変更処理で一貫してトークン検証を実施する必要があります。

また、トークンをURLパラメータに含めてしまうという間違いも見られます。GETリクエストのクエリ文字列にトークンを含めると、Refererヘッダやブラウザの履歴にトークン値が記録されてしまい、セキュリティ上のリスクとなります。トークンは必ずPOSTパラメータやHTTPヘッダーで送信するようにしましょう。

トークンの有効期限管理も重要です。一度生成したトークンを長時間使い回していると、トークン値が漏洩するリスクが高まります。セッションごとにトークンを更新したり、一定時間で無効化したりといった運用が求められます。

Ajax・SPAでの実装漏れ

近年増えているSPA(シングルページアプリケーション)やAjaxを多用するサイトでは、従来のフォーム送信とは異なる実装が必要になります。

JavaScriptからのリクエストでは、CSRFトークンをHTTPヘッダー(例えばX-CSRF-Token)に含めて送信するのが一般的です。しかし、この実装を忘れたり、一部のAPIエンドポイントでのみ実装が漏れたりするケースがあります。

また、JSON APIとして実装する場合、Content-Typeヘッダをチェックすることも重要です。application/jsonでのみリクエストを受け付けるようにすることで、通常のフォーム送信によるCSRF攻撃を防げます。

ただし、これだけではXMLHttpRequestを使った高度な攻撃には対応できないため、やはりトークンベースの検証と組み合わせることが推奨されます。

APIのCSRF対策

REST APIやGraphQL APIを提供している場合も、CSRF対策は必要です。「APIだから大丈夫」という思い込みは危険です。

特に、Cookie認証を使っているAPIは、通常のWebアプリケーションと同様にCSRF攻撃のリスクがあります。外部サイトのJavaScriptから、利用者のブラウザを経由してAPIを呼び出すことが可能だからです。

APIでは、Bearer トークンを使った認証方式(OAuth 2.0など)を採用することで、Cookie認証のリスクを回避できます。トークンは外部サイトから取得できないため、CSRF攻撃の成功率を大幅に下げられます。

ただし、認証方式を変更できない場合は、通常のWebアプリケーションと同様に、CSRFトークンやカスタムヘッダーによる検証を実装する必要があります。

脆弱性診断とセキュリティテスト

対策を実装したら、それで終わりではありません。実際に脆弱性が残っていないか、定期的に確認することが重要です。

手動での検証方法

開発段階では、簡単な手動テストでCSRF脆弱性の有無を確認できます。

まず、重要な処理を実行するページのHTMLソースを確認し、CSRFトークンが含まれているかチェックします。フォームのhiddenフィールドやJavaScriptのコード内に、ランダムな値が埋め込まれていることを確認しましょう。

次に、ブラウザの開発者ツールを使って、実際にリクエストを送信した際のHTTPヘッダーやパラメータを確認します。トークン値が正しく送信されているか、サーバー側で検証が行われているかを確認できます。

簡易的な攻撃シミュレーションとして、HTMLファイルを作成して外部サイトからのリクエストを再現することもできます。自分で作成した罠ページから、対象サイトにPOSTリクエストを送信してみて、処理が実行されてしまわないか確認します。

自動脆弱性診断ツール

手動での確認には限界があるため、自動脆弱性診断ツールを活用することも効果的です。

OWASP ZAPやBurp Suiteといったツールは、CSRF脆弱性を含む様々なセキュリティ問題を自動的に検出できます。これらのツールは、Webアプリケーションをクロールしながら、各種の攻撃パターンを試行し、脆弱性の有無を報告してくれます。

商用の脆弱性診断サービスでは、より高度な検査が可能です。専門のセキュリティエンジニアが、ツールでは発見できない複雑な脆弱性も手動で確認してくれます。

特に、リリース前や大規模なアップデート時には、プロによる脆弱性診断を受けることが推奨されます。開発チーム内だけでは見落としがちな問題点を、第三者の視点で発見できるメリットがあります。

継続的なセキュリティ監視

脆弱性対策は、一度実施すれば終わりというものではありません。新しい攻撃手法が日々発見されており、継続的な監視と改善が必要です。

フレームワークやライブラリのアップデートには注意を払いましょう。セキュリティパッチがリリースされたら、速やかに適用することが重要です。古いバージョンを使い続けることは、既知の脆弱性を放置することと同じです。

また、セキュリティ情報をチェックする習慣も大切です。IPAや JPCERT/CCといった組織が発信する脆弱性情報、CVE(Common Vulnerabilities and Exposures)データベースなどを定期的に確認し、自サイトに影響する脆弱性がないか調べましょう。

開発チーム内でセキュリティ教育を実施することも効果的です。すべての開発者がセキュリティの基本を理解していれば、コードレビューの段階で脆弱性を発見しやすくなります。

まとめ

CSRF(クロスサイトリクエストフォージェリ)は、利用者が意図しない処理を勝手に実行させられてしまう深刻な脆弱性です。金銭被害や個人情報の漏洩、さらには刑事事件に巻き込まれるリスクさえあります。

攻撃の仕組みを理解すると、外部サイトから正規サイトへリクエストを送信させることで、ログイン中の利用者のセッションを悪用するという巧妙な手口であることがわかります。GETメソッドでもPOSTメソッドでも攻撃は可能であり、単にHTTPメソッドを変更するだけでは対策として不十分です。

効果的な対策としては、CSRFトークンの実装が最も確実です。予測不可能なランダム値を使ってリクエストの正当性を検証することで、外部からの不正なリクエストを確実に弾くことができます。Refererヘッダの検証やSameSite Cookie属性の活用を組み合わせることで、多層的な防御を実現できます。

利用者側でも、ログアウトの徹底や不審なリンクの回避といった基本的な注意を払うことで、被害のリスクを減らせます。サービス提供者側は、実装だけでなく定期的な脆弱性診断を通じて、セキュリティを継続的に改善していく必要があります。

セキュリティは一度対策すれば終わりではなく、技術の進化とともに常にアップデートしていくべき領域です。CSRF対策を適切に実施し、安全なWebサービスを提供していきましょう。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!