CSRFとは? †
クロスサイトリクエストフォージェリ(Cross site request forgeries, 略記:CSRF,またはXSRF)とは、WWW における攻撃手法の一つ。
具体例として、掲示板に意図しない書き込みをさせられたり、オンラインショップで買い物をさせられたりするなどの被害が起こる。
原理
攻撃の大まかな流れは以下の通り。
1. 攻撃者が、攻撃用の Web ページを作成して WWW 上に公開する。
(WWW上ででなくとも、未対策のHTMLメーラーにウェブページをHTMLメールとして送信するだけでもよい。)
2. 第三者が、攻撃用の Web ページにアクセスする。
3. 第三者は、攻撃者が用意した任意の HTTP リクエストを送信させられる。
4. 送信させられた HTTP リクエストによって、攻撃者の意図した操作が行われる。
(ここで「第三者」とは、被攻撃サイトに意図せずアクセスさせられると言う意味で用いている。)
対策
Webサイト管理者側
第三者が知り得ない情報をフォームに入力させる(あるいはフォームの hidden パラメータに設定しておく)というのが基本的な対策方針である。ここで利用する第三者が知り得ない情報は、推測されにくい文字列であり、かつ総当り攻撃に対して耐性がある必要がある。具体的には以下の方法が挙げられる。
認証情報を入力させる
認証制の Web システムの場合、入力フォームにユーザIDとパスワードを含めるという方法がある。システムの利用者から見れば、既にログイン画面で認証を行っているため冗長な操作であるが、クロスサイトリクエストフォージェリの対策としては最も効果がある。
ワンタイムトークンを利用する
入力フォームに、第三者に推測されにくい文字列を hidden パラメータとして指定しておき、フォームの情報を受け取る段階でそのパラメータの整合性をチェックするという方法である。そのパラメータが整合性のチェックでしか使われない一時的なデータであることが多いために「ワンタイムトークン」と呼ばれる。但し、第三者が知り得ない情報として有効である限りは、必ずしも「ワンタイム」である必要は無い。
- CSRF(クロス・サイト・リクエスト・フォージェリー)とは、Webサイトで、予期せぬ画面遷移を引き起こす攻撃手法のことです。
- CSRF対策として、「ワンタイムトークン」(一時的な識別符号)を使う方法があります。
- 「ワンタイムトークン」は、別名「ワンタイムチケット」とも呼ばれています。
ワンタイムチケットの有用性 †
ワンタイムチケット方式は、必ずしも万全というわけではない、という指摘があります。
高木浩光@自宅の日記 - CSRF対策に「ワンタイムトークン」方式を推奨しない理由, hiddenパラメタは漏れやすいのか?
画面遷移を完全に制御するのは自然な実装であるが、その実装はオーバースペックであるし、後からそのように変更するのは大変すぎる。
理想的な対策の一つとして、サーバーサイドで「ページ遷移」を制御する方法が提案されていました。
数あるPHPフレームワークの中だと、「Piece Framework」のように、ページ遷移を制御する機能(Piece Flow)を提供しているフレームワークもありますね!
とりあえず、何もCSRF対策をしないよりはマシなので、ここではワンタイムチケット方式で、CodeIgniterのCSRF対策をやってみましょう。
参考リンク †
- CodeIgniterの学習 23 - ワンタイムチケット(ワンタイムトークン)の機能を作って、CSRF対策をちょっとした気分になってみる - ヌル日記
http://d.hatena.ne.jp/dix3/20081017/1224196292
- CodeIgniter 2.0に追加されたCSRF保護オプションの挙動 - e2esound.com業務日誌
http://www.e2esound.com/wp/2011/02/14/csrf_options_in_codeigniter_2/これまでのCSRF対策
CodeIgniter1.7系までは、以下のようにワンタイムチケットを生成してCERF対策を行っていました。
1. controllerでワンタイムチケットを生成
2. sessionクラスを使って、ワンタイムチケットをsessionに保存
3. viewの中でformのhiddenフィールドにワンタイムチケットをセット
4. ユーザーによるform処理
5. $_POSTで送られてきたワンタイムチケットとsessionに保存してあるワンタイムチケットを照合
6. TRUEであれば処理継続、FALSEであれば処理中止
この方法だと、controllerの中で、照合を書かなければいけませんでした。
2.0で追加されたCSRF保護の使い方
とても簡単です。まずapplication/config/config.phpの設定を変更します。
$config['csrf_protection'] = TRUE;
次に、全てのformタグをformヘルパーのform_open()で出力するようにします。
すると、form_open()で出力したすぐ下にhiddenフィールドが作られ、そこにワンタイムチケットがセットされます。このチケットの照合作業は自動で行われる為、controllerに何かを記述することはありません。
ワンタイムチケットの導入 †
CodeIgniter2.0以降のバージョンでは、自動的にワンタイムチケットを利用できる機能が追加されていました。
- CodeIgniter ユーザガイド 日本語版 Version 2.0.1 › セキュリティクラス
http://codeigniter.jp/user_guide_ja/libraries/security.htmlセキュリティクラスは,入力データの処理によりセキュアなアプリケーションの開発を手助けします。
クロスサイトリクエストフォージェリ (CSRF)
CSRF 保護を有効にするには,application/config/config.php を開いて次のように設定します:
$config['csrf_protection'] = TRUE;
フォームヘルパ の form_open() 関数を使用すると,フォームに対して CSRF 保護用の hidden フィールドが自動的に挿入されます。
- CodeIgniterの設定ファイルで、「csrf_protection」をTRUEにする。
application/config/config.php
<?php $config['csrf_protection'] = TRUE; ?>
- そして、Formヘルパーのform_open()関数を使って、formタグを出力する。
たったこれだけで、formタグの直下にワンタイムチケットのコードが自動的に挿入され、ページ遷移をチェックをしてくれるとのこと。
ワォ~、超簡単ですね!(・∀・)