クロスサイトリクエストフォージェリ(CSRF)の攻撃手法を整理してみた。

商品注文サイトを例にしてクロスサイトスクリプトフォージェリ(CSRF)の攻撃手法を整理してみようと思います。商品注文サイトはログイン画面で顧客の認証を行い、認証OKとなった場合に商品を注文できるようになっています。商品を注文する画面は、注文画面、確認画面、完了画面で構成されているとします。

  1. 顧客は注文画面で商品を入力して「注文」ボタンを押下します。
  2. 確認画面に遷移し、注文内容に間違いがなければ「確定」ボタンを押下します。
  3. 注文が完了し、完了画面が表示されます。

確認画面から完了画面に遷移するところですが、確認画面のフォームは以下であったとします。

このフォームでは確定ボタンを押下(submit)すると、syohin に”りんご”、kosu に”1”を設定して POST メソッドでPHPプログラム(commit.php)に値を引き渡します。PHPプログラムでは注文処理を行ってから完了画面を表示するHTMLをブラウザに返します。

仮に、この商品注文サイトにCSRFに対する脆弱性があったものとして(脆弱性については後述)、CSRFの攻撃を受けてしまった場合のやりとりは以下のようになります。商品注文サイトを攻撃対象のサイトと呼んでいます。

①顧客が攻撃対象のサイトにアクセスしてログインします。
②認証を行いOKであればセッションIDが顧客に発行されます。
③顧客が(気づかずに)悪意あるサイトにアクセスします。
④悪意あるサイトからレスポンスが返されます。
⑤仕込まれたJavaScriptがブラウザ上で実行されます。
⑥商品の注文確定処理が行われてしまいます。

①〜⑥の順に説明します。

[広告]

クロスサイトリクエストフォージェリによる攻撃手法

■①顧客が攻撃対象のサイトにアクセスしてログインします。

ブラウザがHTTPで商品注文サイトにアクセスします。ログイン画面が表示されて顧客はユーザ/パスワードの認証情報を入力します。

■②認証を行いOKであればセッションIDが顧客に発行されます。

商品注文サイトでは顧客の認証を行い、認証OKであればセッションIDを発行します。ブラウザは商品注文サイトにアクセスするときはこのセッションIDを設定してアクセスし、商品注文サイトはセッションIDで顧客を認証します。

■③顧客が(気づかずに)悪意あるサイトにアクセスします。

この状態(顧客が商品注文サイトにログイン済みの状態)で、悪意あるサイトにアクセスします。

■④悪意あるサイトからレスポンスが返されます。

このレスポンスの中に攻撃コード(JavaScript)が含まれています。以下が攻撃コードの例です。この例では勝手に「みかん10個を注文する」コードです。

■⑤仕込まれたJavaScriptがブラウザ上で実行されます。

このJavaScriptは画面表示された際に確定ボタンを押下(submit)の処理を自動で行ってしまいます。処理の内容としては、syohin に”みかん”、kosu に”10”を設定して commit.php に値を引き渡します。つまり、勝手に「みかん10個を注文する」コードとなっています。

■⑥商品の注文確定処理が行われてしまいます。

ブラウザから渡ってきた注文内容をそのまま処理してしまいます。悪意あるサイトにアクセス(もしくは、悪意あるサイトのリンクをクリック)しただけで、意図しない注文が確定してしまうことになります。

[広告]

対策はどうしたらよいか?

ブラウザからの通常のリクエストも悪意のあるサイトを経由したリクエストも正規のセッションIDが設定されているのでセッションIDで違いを見分けるわけにはいきません。そこで着目するべきは画面遷移です。この例でいうと問題になっているのは確認画面から完了画面への遷移のときで、その画面遷移を制御するPHPプログラム(commit.php)が、本来の確認画面からの遷移だったか?の判断ができるようになれば問題はなくなります。以下にその方法を書いてみます。

■Refererで遷移元の画面を確認する。

上記の⑥で commit.php にアクセスがあった際にHTTPヘッダーのRefererを確認します。Refererが確認画面のURLであれば正当なリクエストと判断します。もし確認画面のURLでない場合は注文処理は行わず、ブラウザにはエラーを返すようにします。ただ、ブラウザの設定によってはRefererを送付しないようになっている場合もあり、注意が必要です。

■hiddenフィールドを使った隠し情報で確認する。

確認画面のフォームをブラウザに送る際に、hiddenフィールドを使って隠し情報もブラウザに連携しておきます。隠し情報は疑似乱数などで、リクエストごとに変わるものです。上記の⑥の際でブラウザから渡ってきた隠し情報を確認し、事前に連携した隠し情報と一致すれば正当なリクエストと判断します。悪意あるサイトを経由した場合はこの隠し情報がない、もしくは一致しないので不正なリクエストとして排除できます。

■確認画面で再度パスワード入力を求める。

これが一番簡単な方法です。顧客にはパスワードを入力してもらい、渡ってきたパスワードが正しいかどうかで判断します。悪意あるサイトが顧客の正しいパスワードを設定することはできません。ただしこの方法は顧客には負担がかかることになります。

クロスサイトリクエストフォージェリ(CSRF)と似たような名前の攻撃で、クロスサイトスクリプティング(XSS)というものがあります。ただこの2つは違うものです。クロスサイトスクリプティングについては前回の記事を見てみてください。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です