Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Set config item (csrf) doesnt work in Codeigniter

I want to turn ON csrf protection only in a few of my controllers, so I have

function __construct() {

    parent::__construct();
    $this->load->library('form_validation');        
    $this->load->library('tank_auth');
    $this->load->helper(array('form', 'url'));
    $this->load->model('user_model', '', true);

    $this->config->set_item('csrf_protection', TRUE);

}

But it doesn't seem to work, although when I do var_dump($this->config) on a page it shows that csrf_protection is TRUE, but the cookies are not set and the form has a hidden field without value

<input type="hidden" name="ci_csrf_token" value="" />

Csrf token name and cookie name are all set, the forms are called with form_open().

Any help would be much appreciated.

Update: So this is not possible from version 2.1.1 because of the line in security class construct if (config_item('csrf_protection') === TRUE) {

Security class is initialized before the controller, so its natural that the config item change in the controller will not affect it.

like image 563
Bndr Avatar asked Apr 05 '13 19:04

Bndr


1 Answers

I have a solution for you. Create a custom application/core/MY_Security.php and put this in it:

<?php if ( !defined( 'BASEPATH' ) ) exit( 'No direct script access allowed' );

class MY_Security extends CI_Security
{
    public function csrf_verify( )
    {
        foreach ( config_item('csrf_excludes') as $exclude )
        {
            $uri = load_class('URI', 'core');
            if ( preg_match( $exclude, $uri->uri_string() ) > 0 )
            {
                // still do input filtering to prevent parameter piggybacking in the form
                if (isset($_COOKIE[$this->_csrf_cookie_name]) && preg_match( '#^[0-9a-f]{32}$#iS', $_COOKIE[$this->_csrf_cookie_name] ) == 0)
                {
                    unset( $_COOKIE[$this->_csrf_cookie_name] );
                }
                return;
            }
        }
        parent::csrf_verify( );
    }
}

This will check the following excludes which you need to put in your application/config.php in the CSRF section:

$config['csrf_excludes'] = array
    ( '@^/?excluded_url_1/?@i'
    , '@^/?excluded_url_2/?@i' );

Every matching URL pattern will be excluded from CSRF checks. You can build regex here at http://rubular.com

cheers

like image 106
Patrick Savalle Avatar answered Sep 25 '22 05:09

Patrick Savalle