JelleP
JelleP

Reputation: 1004

Security cookie_secure CSRF not working

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()); ?>

Upvotes: 0

Views: 1613

Answers (3)

MERT DOĞAN
MERT DOĞAN

Reputation: 3116

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.

Upvotes: 0

Daniel Marashlian
Daniel Marashlian

Reputation: 11

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;
}

Upvotes: 1

Mikolaj
Mikolaj

Reputation: 708

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().

Upvotes: 0

Related Questions