Search code examples
phpcodeignitercsrf

Codeigniter CSRF protection VS tabs


In the newish CodeIgniter v3, CSRF tokens are only valid once. As a result, I'm having some trouble dealing with multiple tabs:

  1. Open a tab with Form1
  2. Open a tab with Form2
  3. Submit the tab with Form 1
  4. Submit the tab with Form 2

Step 4 will results in a CSRF error. Obviously this is not ideal... How is onemeant to solve this?


Solution

  • Background

    There is no need to regenerate the CSRF token upon each form submission. There is little security benefit - if the attacker could retrieve the token from your page then they already have won. This will enable your site to run cross-tabs without error.

    See this page for some background on the security aspect: Why [you shouldn't] refresh CSRF token per form request?.

    CodeIgniter v3

    v3 uses a configuration item named csrf_regenerate. Set this to FALSE to prevent regeneration after each request.

    CodeIgniter v2

    The code CodeIgniter uses is discussed in this post: CSRF Protection in CodeIgniter 2.0: A closer look. The relevant code is below:

    function csrf_verify()
    {
        // If no POST data exists we will set the CSRF cookie
        if (count($_POST) == 0)
        {
            return $this>csrf_set_cookie();
        }
    
        // Do the tokens exist in both the _POST and _COOKIE arrays?
        if ( ! isset($_POST[$this->csrf_token_name]) OR
             ! isset($_COOKIE[$this->csrf_cookie_name]) )
        {
            $this->csrf_show_error();
        }
    
        // Do the tokens match?
        if ( $_POST[$this->csrf_token_name]
             != $_COOKIE[$this->csrf_cookie_name] )
        {
            $this->csrf_show_error();
        }
    
        // We kill this since we're done and we don't
        // want to polute the _POST array
        unset($_POST[$this->csrf_token_name]);
    
        // Re-generate CSRF Token and Cookie
        unset($_COOKIE[$this->csrf_cookie_name]);
        $this->_csrf_set_hash();
        $this->csrf_set_cookie();
    
        log_message('debug', "CSRF token verified ");
    }
    

    Simply remove the following code from the function:

    // Re-generate CSRF Token and Cookie
    unset($_COOKIE[$this->csrf_cookie_name]);
    $this->_csrf_set_hash();
    $this->csrf_set_cookie();