EthnaのCSRF対策

EthnaはCSRF対策機能まで実装してある。
すんばらしい。
クロスサイトリクエストフォージェリの対策コードについて

で、本来の使い方と違うかもしれないけど、CSRF対策限らず、「ある時点からセッションの内容が変更された」時のチェックとかにも何気に使えるので、これを応用して拡張した時のメモ。


■テンプレートにIDを埋め込む時、GETで渡したい場合
これ公式サイトにはPOST時のことしか載っていなかったけど、getの時のも用意されてそうだなーとソースを見たら載ってた。

{csrfid type="get"}で
ethna_csrf=xxxxxxxxxxxxx~
ってコードが生成されるんで、こんな感じに書くとOK

a href="http://hogehoge.com/index.php&{csrfid type="get"}"


■Sessionが匿名の奴(anonymous)の時も使いたい
Ethna_Plugin_Csrf_Sessionでは、anonymousだと弾かれてまう。
ので以下のように独自のプラグインを作成

class Hoge_Plugin_Csrf_Session extends Ethna_Plugin_Csrf
{
    /** @var    object  Ethna_Session    セッションオブジェクト */
    var $session;

    /** @var    bool    anonymous        セッションのanonymous */
    var $anonymous;

    /**
     *  Hoge_Plugin_Csrfのコンストラクタ
     *
     *  @access public
     *  @param  object  Ethna_Controller    &$controller    コントローラオブジェクト
     */
    function Hoge_Plugin_Csrf_Session(&$controller)
    {
        parent::Ethna_Plugin_Csrf($controller);

        // オブジェクトの設定
        $this->session   =& $this->controller->getSession();
+       $this->anonymous =  $this->session->isAnonymous();
    }

    /**
     *  トークンをViewとローカルファイルにセットする
     *
     *  @access public
     *  @return boolean  成功か失敗か
     */
    function set()
    {
-       if (! $this->session->isStart() {
-           $this->session->start();
-       }
+       if (! $this->session->isStart($this->anonymous)) {
+           $this->session->start(0, $anonymous);
+       }

        $token = $this->session->get($this->token_name);
        if ($token !== null) {
            return true;
        }

        $key = $this->_generateKey();
        $this->session->set($this->token_name, $key);

        return true;
    }

    /**
     *  トークンIDを取得する
     *
     *  @access public
     *  @return string トークンIDを返す。
     */
    function get()
-       if (! $this->session->isStart() {
-           $this->session->start();
-       }
+       if (! $this->session->isStart($this->anonymous)) {
+           $this->session->start(0, $anonymous);
+       }

        return $this->session->get($this->token_name);
    }

    /**
     *  トークンIDを削除する
     *
     *  @access public
     */
    function remove()
    {
-       if (! $this->session->isStart() {
-           $this->session->start();
-       }
+       if (! $this->session->isStart($this->anonymous)) {
+           $this->session->start(0, $anonymous);
+       }

        $this->session->remove($this->token_name);
    }

}

あと、リセットしたい場合(今までのを破棄&再発行)もあったので、関数追加した。
    /**
     *  トークンをViewとローカルファイルにリセットする
     *
     *  @access public
     */
    function reset()
    {
        $this->remove();
        $this->set();
    }

これだけじゃ折角追加した関数が使われないので、Hoge_Util.phpも独自に作成。
こっちは継承させて、以下の関数を追加。
デバッグ用にgetCsrfID()って関数も作ってみた。

    /**
     *  CSRFをリセットする
     *
     *  @access public
     *  @return bool    true:成功
     */
    function resetCsrfID()
    {
        $c =& Ethna_Controller::getInstance();
        $name = $c->config->get('csrf');
        
        if (is_null($name)) {
            $name = 'Session';
        }
        
        $plugin =& $c->getPlugin('Csrf', $name);
        $csrf =& $plugin->getPlugin('Csrf', $name);
        return $csrf->reset();
    }

    /**
     *  CsrfIDを取得する
     *
     *  @access public
     *  @return bool    true:成功
     */
    function getCsrfID()
    {
        $c =& Ethna_Controller::getInstance();
        $name = $c->config->get('csrf');
        
        if (is_null($name)) {
            $name = 'Session';
        }
        
        $plugin =& $c->getPlugin('Csrf', $name);
        $csrf =& $plugin->getPlugin('Csrf', $name);
        return $csrf->get();
    }
}

これで
Hoge_Util::getCsrfID();
とかすれば使えるように。
もう、どんどん拡張してるなー。
でもでら便利。

コメント

アーカイブ

2012

  • 01
  • 02
  • 03
  • 04
  • 05
  • 06
  • 07
  • 08
  • 09
  • 10
  • 11
  • 12

2011

2010

2009

2008

2007

コンタクト

longkey1[at]gmail[dot]com