CodeIgniter 2.0に追加されたCSRF保護オプションの挙動

さて、今週土曜日はCodeIgniterカンファレンスですね。
カンファレンスに向けて、サンプル用のアプリを作ったり資料を書いたりとバタバタしています。

アプリを作る中で、2.0から搭載されたCSRF保護オプションの挙動について調べたので忘れないうちにメモです。

これまでの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に何かを記述することはありません。

CSRF保護の挙動

具体的な挙動について調査してみました。

  1. サイトにアクセスされた時点で、ユーザーのCookieにチケットを仕込む(有効なチケットがある場合には、そのまま)
  2. form_open()が行われる度にhiddenフィールドを設定
  3. $_POSTが行われたのに、$_POSTの中にワンタイムチケットがない、又はCookieにセットしたチケットと合わない→エラー画面へ
  4. エラー表示しない場合、$_POSTの中のチケットを削除(Inputクラスで処理されるので、controllerでvar_dump()しても出てこない)
  5. 値を再生成してCookieにセット?(expireが有効であれば、つまりユーザーのcookieにまだkeyが残っていればそれを使う)

だいたいこんな感じらしい。

内容を確認した場合は、system/libraries/Security.phpとsystem/helper/form_helper.php、system/core/Input.phpを確認してみて下さい。

ちょっとした疑問

実際にform_open()を使って表示させた時に、

<div class="hidden">
<input type="hidden" name="csrf_test_name" value="xxxxxxxxxxxxxxxxxxxx">
</div>

なぜdivで囲んでるんだろうか…

sessionに入れればいいのに、と思ったりもしましたが、多分そこはそもそもsessionクラス使うのか使わないのかという選択肢があるのでCookieに入っているんだろうと思います。

気に入らなければ後で変えればいい話で。それが簡単にできるのもCIのいいところ。これまで呼び出していたsessionクラスを使わなくてもformの処理ができるようになったっていうのは大きいと思いました。

CodeIgniter 2.0に追加されたCSRF保護オプションの挙動」への3件のフィードバック

  1. ピンバック: お問い合わせフォーム等のメールフォームのスパム対策 | Binbo-Special – WEB制作や運営に関する楽屋話 -

  2. ピンバック: Tweets that mention CodeIgniter 2.0に追加されたCSRF保護オプションの挙動 - e2esound.com業務日誌 -- Topsy.com

コメントを残す

メールアドレスが公開されることはありません。