サイト脆弱性をチェックしよう! -- 第14回:CSRF(クロスサイト・リクエストフォージェリ)の検査方法
<目次>
目次[非表示]
クロスサイト・スクリプティングという脆弱性を知っている方は多いと思うが、クロスサイト・リクエストフォージェリという脆弱性を知っている方は多くないだろう。
アプリケーション開発者も同様で、十分な対策が進まずに脆弱性が存在するアプリケーションを見ることもめずらしくない。クロスサイト・リクエストフォージェリはWebアプリケーション全体に影響を与えるため、重要処理を行うWebアプリケーションにおいて対策は必須だ。そこで今回はクロスサイト・リクエストフォージェリについて説明していきたいと思う。
クロスサイト・リクエストフォージェリとは
決済処理等の重要な処理を行う際、本人が意図したリクエストであることを確認する必要がある。本人が意図したリクエストであることをアプリケーション側でチェックする仕組みがないと、攻撃者があらかじめ用意した罠サイトを閲覧しただけで、利用者の意図しない不正なリクエストが送られ、強制的に処理を実行させられてしまう。このような脆弱性があることを「クロスサイト・リクエストフォージェリ」と呼ぶ。
クロスサイト・リクエストフォージェリの具体的な攻撃手法は以下の通りだ。
クロスサイト・リクエストフォージェリの攻撃手法
図1:CSRFを利用した攻撃例
- 利用者がWebサイトにログインをする。
- Webアプリケーション側はセッションIDを発行する。
- 認証で使われるセッションIDはCookieに保存され、有効期限が切れるか、または利用者がセッションを破棄するまでログイン状態が維持される。
- 利用者は罠に気付かず、攻撃者があらかじめ用意した罠サイトにアクセスする。
- 罠サイトに用意されていた不正なリクエストがWebアプリケーションに送信される。
- 脆弱性をもつWebアプリケーションは不正なリクエストを処理してしまい、利用者のアカウントで本人が意図しない処理が実行される。
次にどのような機能をもつWebアプリケーションで注意が必要か説明する。
どのようなWebサイトで注意が必要か
ターゲットとして狙われる機能は、主に取り消しができない重要処理を行うWebサイトだ。利用者アカウントによるパスワードやメールアドレスの変更、問い合わせフォームや掲示板の書き込みなど多岐にわたる。
特にネットバンキングやショッピングサイトなど、口座からの送金やクレジットカード決済など金銭処理を行うサイトの場合、攻撃による被害が大きくなるため対策は必須としたいところだ。
例えば自社のWebサイトがこのような重要機能を持っている場合、どのような検査を行えばクロスサイト・リクエストフォージェリ脆弱性の有無を調べられるのか、次の項で説明する。
クロスサイト・リクエストフォージェリの検査方法
クロスサイト・リクエストフォージェリの有無を確認する箇所は、「登録」や「送信」などの確定処理の直前で送信されるパラメータに対して検査を実施する。
具体的には、[入力]→[確認]→[実行]のような画面遷移の場合、[確認]画面で送信されるリクエストに含まれるパラメータに対して検査を実施する。
まず、Cookieなどリクエストヘッダに含まれた値によってセッション管理が行われている確定処理において、以下の秘密情報がリクエストに含まれているか確認する。
- セッションID
- トークン
- パスワード
- CAPTCHA
上記1~4の秘密情報が含まれている場合は、該当のパラメータに対してさらに以下の検査を実施する。
- 該当パラメータの値を他ユーザの値に変更して処理が実行されるか確認
- 該当パラメータごと削除して処理が実行されるか確認
- 該当パラメータの値を削除して処理が実行されるか確認
上記の検査パターンと合わせてRefererのチェックも行う。
- Refererを削除、または正規のURLではない値に変更して、処理が行われるか確認
脆弱性がある場合の結果としては、「(1) 1~4に該当する秘密情報を送信していない場合」、または「(2) トークンの値やRefererが不正でも、正常な処理が実行できる場合」にこの脆弱性が存在すると判断する。
クロスサイト・リクエストフォージェリの対策
クロスサイト・リクエストフォージェリは、Webアプリケーション全体に影響が及ぶので、設計段階から対策を行うのが望ましい。しかし既に稼働しているアプリケーションで脆弱性が発見されたときはどのような対策を行えばよいのだろうか。 具体的な対策としては、以下の3点が挙げられる。
- トークンを埋め込み、利用者が意図したリクエストかチェックする
- 重要な処理の実行時にパスワードの入力を求める
- Refererヘッダが正しいリンク元かチェックする
なお、以下で説明する対策については、クロスサイト・スクリプティングの脆弱性が混入していないことを前提としている。
1.トークンを埋め込み、利用者が意図したリクエストかチェックする
重要処理を行う際に、第三者が知りえない「トークン」という情報を要求する仕組みがあれば、攻撃者によって不正なリクエストを送信させられても、アプリケーション側で判別することができるため、攻撃を防ぐことができる。
重要処理を行うページのhidden(画面上には表示されない項目)にトークンをセットし、処理が行われる際に一緒にサーバに送信する。この送信されたトークンの値とサーバ側で保管されたトークンの値が等しければ、本人が意図したリクエストであることを確認できる。送られてくるトークンの値が異なる場合や空の場合は、エラーとして処理を実行しないよう実装する必要がある。
この方式は様々なアプリケーションで採用されており、攻撃の防御に対応したフレームワークを利用すれば、トークンの生成とチェック機能を有効化することで対策が可能だ。また、フレームワークの機能を利用することで、既存アプリケーションの修正でも開発工数を抑えることができる。
フレームワークを使用せずにこの方式を採用する場合は、第三者に推測されにくい「暗号論的擬似乱数生成器」を用いて乱数を生成し、対策することを推奨する。
この方式を採用する際の注意点としては、トークンの値はPOSTメソッドで送信する必要があるということだ。GETメソッドの場合、Refererやアドレスバーからトークンの値が漏れて悪用される可能性があるので注意する必要がある。
2.重要な処理の実行時にパスワードの入力を求める
重要処理を実行する直前でパスワードの入力を求めることで、本人の意図したリクエストであることを確認する方式だ。[入力]→[確認]→[実行]のように画面を遷移するアプリケーションの場合、確認画面でパスワードを入力させ、実行ページで確認を行う。
この方式を採用する際の注意点は、パスワードを入力するため、WebサイトがSSL/TLSで暗号化されている必要があるというところだ。HTTP通信の場合、入力したパスワードが平文で送られるため、この方式を採用するにはWebサイトの暗号化が前提となる。
また、画面の追加を行うため、既存のアプリケーションを改修する場合は開発工数が大きくなる。従って、これから新規でアプリケーションを開発する場合を除き、画面設計の変更を伴わない方式で対策をすることを推奨する。
これから新規でアプリケーションを開発する場合は、要件定義や設計工程であらかじめ重要な処理を行う画面(機能)を洗い出し、対策を行うとよい。
3.Refererが正しいリンク元かチェックする
正規のリクエストと攻撃のリクエストを見分けるにはRefererを確認すればよい。なぜならRefererには直前まで訪れていたWebページのURL(リンク元)が記載されているからだ。重要処理のリクエストを送信する際に、Refererヘッダが正しい画面を遷移していない場合、罠サイトを経由した不正なリクエストである可能性が高い。
Refererチェックは有効な対策の一つではあるものの、この方式を採用する際には注意点がある。
プライバシーやセキュリティの観点から、利用者はRefererを送らないように設定したり、プロキシサーバ側でRefererを削除したりすることが可能だ。Refererがないと利用者がWebサイトを利用できなくなる可能性があることから、社内のシステムなど環境が特定できる場合にこの方式を採用するとよいだろう。
最後に、重要処理が行われた場合に事前に登録したメールアドレスに通知設定をする対策方法もあるが、対処療法であるため推奨はしない。暫定の対策としてならよいが、脆弱性の根本的な解決に向けて1~3の対策を実施することを推奨する。
まとめ
今回はあまり知られていないクロスサイト・リクエストフォージェリの脆弱性について説明した。次回以降も脆弱性の具体的な検査手法について説明していきたい。