0

I am currently using Codeigniter and like to enable in the config.php:

$config['cookie_secure']    = TRUE; 

I am also using:

$config['csrf_protection'] = TRUE;
$config['csrf_token_name'] = '***';
$config['csrf_cookie_name'] = '***';
$config['csrf_expire'] = 7200;

The connection is https only. But when I am using the cookie_secure option, the CSRF is not working any more and gives this:

The action you have requested is not allowed.

Codeigniter cannot store the CSRF in an cookie because of this measure. How can I solve it? I like to use both security measures.

<--- EDIT --->

<form action="<?php echo base_url().'login/'; ?>" method="post">

  <?php echo form_hidden($this->security->get_csrf_token_name(), $this->security->get_csrf_hash()); ?>
JelleP
  • 976
  • 7
  • 20
  • 39

3 Answers3

1

I was running into the same issue when I had both cookie_secure set to true and csrf_protection set to true.

What I first noticed was the CSRF cookie wasn't being set.

Looking at the csrf_set_cookie() function in /system/core/Security.php, you'll see:

/**
 * Set Cross Site Request Forgery Protection Cookie
 *
 * @return  object
 */
public function csrf_set_cookie()
{
    $expire = time() + $this->_csrf_expire;
    $secure_cookie = (config_item('cookie_secure') === TRUE) ? 1 : 0;

    if ($secure_cookie && (empty($_SERVER['HTTPS']) OR strtolower($_SERVER['HTTPS']) === 'off'))
    {
        return FALSE;
    }

    setcookie($this->_csrf_cookie_name, $this->_csrf_hash, $expire, config_item('cookie_path'), config_item('cookie_domain'), $secure_cookie);

    log_message('debug', "CRSF cookie Set");

    return $this;
}

Though, like most, I use a load balancer for SSL termination. The individual servers don't know the traffic is over HTTPS, since the traffic is sent to each server over port 80 on the internal network. This is what the HTTP_X_FORWARDED_PROTO is for.

I ended up overwriting the csrf_set_cookie() in my /application/core/MY_Security.php to fix this:

/**
 * Set Cross Site Request Forgery Protection Cookie
 *
 * @return  object
 */
public function csrf_set_cookie()
{
    $expire = time() + $this->_csrf_expire;
    $secure_cookie = (config_item('cookie_secure') === TRUE) ? 1 : 0;

    if (
        $secure_cookie &&
        (empty($_SERVER['HTTPS']) OR strtolower($_SERVER['HTTPS']) === 'off') &&
        (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] != 'https')
    ) {
        return FALSE;
    }

    setcookie($this->_csrf_cookie_name, $this->_csrf_hash, $expire, config_item('cookie_path'), config_item('cookie_domain'), $secure_cookie);

    log_message('debug', "CRSF cookie Set");

    return $this;
}
0

It looks like this may handle the problem, make sure you have form_open() in your code. Per the documentation on codeigniter form helper,

Creates an opening form tag with a base URL...

This should also add the csrf automatically without form_hidden().

Mikolaj
  • 688
  • 8
  • 19
0

If you want to solve this CODEIGNITER BUG, you can set like below:

$config['sess_cookie_name'] = 'ci_projectname_session';

...

...

$config['cookie_prefix']    = 'ci_projectname_';

As example above, cookie prefix and cookie name must begin as same.

MERT DOĞAN
  • 2,864
  • 26
  • 28