Hazem Taha
Hazem Taha

Reputation: 1184

How to enable CSRF Protection for specific forms in codeigniter

I'm working right now on a web application which contains about 200 html forms, I'm asked to add CSRF Protection to the login and register forms only. I've enabled the CSRF Protection form the configuration file but I'll have to use the form helper library in all the 200 forms. It is obvious that it would be very exhausting to change the opening tags of the 200 forms from

<form action="user/foo" method="post" id="formId">

to

<?php echo form_open(base_url().'user/foo' array('id' => 'formId'));  ?>

So, I'm wondering if there is a method which I can use to enable the csrf protection for only the register and login forms ? Thanks so much.

Upvotes: 1

Views: 4949

Answers (2)

proyoussef
proyoussef

Reputation: 31

You can do this by editing the config.php file :

$config['csrf_protection'] = FALSE;

if (isset($_SERVER["REQUEST_URI"])) {
    if(stripos($_SERVER["REQUEST_URI"],'/login') !== FALSE || stripos($_SERVER["REQUEST_URI"],'/register') !== FALSE ) {
        $config['csrf_protection'] = TRUE;
    }
} 

And in your view files, add this :

<input type="hidden" name="<?php echo $this->security->get_csrf_token_name(); ?>" value="<?php echo $this->security->get_csrf_hash();?>" />

Or simply use the form_open() function to add the hidden CSRF token field automatically.

Upvotes: 3

JC Sama
JC Sama

Reputation: 2204

Yes you can, and you have two choices :

1- The easy way by just modifying "application/config.php" file like this :

$config['csrf_protection'] = FALSE;
if (isset($_SERVER["REQUEST_URI"]))
    if(stripos($_SERVER["REQUEST_URI"],'/login') !== FALSE
            || stripos($_SERVER["REQUEST_URI"],'/register') !== FALSE
    )
        $config['csrf_protection'] = TRUE;

2- By overriding the Security Class and creating a Hook Class as follow :

2-1 application/core/My_Security.php :

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

class MY_Security extends CI_Security
{
    public function regenerate_csrf_hash()
    {
            // CSRF config
            foreach (array('csrf_expire', 'csrf_token_name', 'csrf_cookie_name') as $key) {
                if (false !== ($val = config_item($key))) {
                    $this->{'_' . $key} = $val;
                }
            }

            // Append application specific cookie prefix
            if (config_item('cookie_prefix')) {
                $this->_csrf_cookie_name = config_item('cookie_prefix') . $this->_csrf_cookie_name;
            }

            // Set the CSRF hash
            $this->_csrf_set_hash();
            $this->csrf_set_cookie();

        }
    }

2-2 application/hooks/EnableOptions.php

<?php

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

class EnableOptions {

    private $ci;

    public function __construct(){
            $this->ci = &get_instance();
        }

    public function enableCSRF()
    {
        if ($this->ci->config->item('csrf_protection') === false) {
            $uri = $this->ci->config->item('enable_csrf_for_uris_only');
            $segment = $this->ci->uri->segment('1'); // 1 : for controller name

            if (in_array($segment, $uri)) {
                $this->ci->config->set_item('csrf_protection', true);
                $this->ci->security->regenerate_csrf_hash();

            }
        }

    }

}

2-3 application/config/hooks.php :

$hook['post_controller_constructor'][] = array(
    'class'    => 'EnableOptions',
    'function' => 'enableCSRF',
    'filename' => 'EnableOptions.php',
    'filepath' => 'hooks',
    'params'   => array()
);

2-4 application/config/config.php : Enable the hooks by modifying "enable_hooks" to true,

$config['enable_hooks'] = TRUE;

and add an extra parameter for URIs,

$config['enable_csrf_for_uris_only'] = array('login', 'register');

That's it.

Upvotes: 2

Related Questions