LoginSignup
30
27

More than 5 years have passed since last update.

Phalcon で CSRF 対策を行う

Last updated at Posted at 2014-05-25

Phalcon で CSRF 対策を行う

内容

Phalcon では CSRF 対策としてワンタイムトークンを生成して用いる.

関連するメソッドは下記の通り.

  • Security#checkToken()
  • Security#getToken()
  • Security#getTokenKey()
  • Security#getSessionToken()

使用例

ビュー側では 下記のように生成する.

<input type="hidden" name="<?php echo $this->security->getTokenKey() ?>"
    value="<?php echo $this->security->getToken() ?>"/>

volt の場合の例.

{{ hidden_field(security.getTokenKey(), "value": security.getToken()) }}

コントローラ内では以下のようにしてチェックする.

if ($this->security->checkToken()) {
  // TODO: CSRF トークンチェックが成功した場合
}

フォーム内で生成して isValid() したい場合は下記のようフォーム内で Indentical バリデーションクラスを用いてチェックするようにする例.

    public function initialize() {
        // CSRF
        $csrf = new Hidden('csrf');

        $csrf->addValidator(new Identical(array(
            'value' => $this->security->getSessionToken(),
            'message' => 'CSRF validation failed'
        )));

        $this->add($csrf);
    }
{{ form.render('csrf', ['value': security.getToken()]) }}

checkToken() は第一引き数に名前を取るので csrf という名前でフォームをレンダリングした場合は checkToken('csrf') でもチェックできる.

使う場合の注意点

  • ビューなどでトークンを埋め込む場合は getToken() を用いたほうがよい
    • getSessionToken()getToken() を呼ばない限りはセットされないため
  • getToken() は1ページ内で一回のみの呼び出しとしたほうがよい
    • checkToken()getSesssionToken() で使われる値は最後に getToken() を呼んだ値となる
    • (追記) 最後に呼ばれた getToken() を使うため別タブで開いたりするとバリデーションエラーになる.認証必須なページならログインフォームで一回生成した後ずっと getSessionToken() を用いるような実装のほうが利便性は高そう.
  • indexAction() の場合 getToken() を読んでいなくても getSessionToken() の値が変更されているらしく, checkToken() や Form クラスでの csrf トークンが正しくてもエラーになってしまう様子(詳細動作未確認).
    • indexAction() 内では csrf トークンを確認するような処理を行わないほうがよさそう. / でなにかやりたい場合は Route クラスを用いて別アクションに変更するようにしたほうがよさそう 参考

ここらへんは フォーラム に書かれてる事が多いのでちょっと見てみると良いかもしれない.

付録

一度も getToken() が呼ばれていないセッションで POST や GET された値が空の場合になぜか checkToken() が true を返す.ただし通常利用では空で送信することはないので問題ないはず.

参考

ドキュメント

セキュリティ — Phalcon 1.3.1 documentation

http://docs.phalconphp.com/ja/latest/reference/security.html#csrf

サンプル

vokuro/app/forms/LoginForm.php at master · phalcon/vokuro

https://github.com/phalcon/vokuro/blob/master/app/forms/LoginForm.php

volt で書いた時の例

problems with csrf - Discussion - Phalcon Framework

http://forum.phalconphp.com/discussion/1658/problems-with-csrf

getToken() を複数呼ぶことについて

CSRF tokens and many forms at one page - Discussion - Phalcon Framework

http://forum.phalconphp.com/discussion/345/csrf-tokens-and-many-forms-at-one-page

checkToken() が true を返す例外について

checkToken() is not enough check value for CSRF Attack? - Discussion - Phalcon Framework

http://forum.phalconphp.com/discussion/2388/checktoken-is-not-enough-check-value-for-csrf-attack-

indexAction で getSessionToken() がちゃんと動かない

PhalconPHP - How to get CSRF working on index page | Ole Aass

http://oleaass.com/phalconphp-get-csrf-working-index-page/

30
27
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
30
27