[eluser]Twisted1919[/eluser]
the problem lies in the csrf_verify method :
Code:
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();
}
// THE PROBLEM STARTS FROM HERE
// We kill this since we're done and we don't want to polute the _POST array
unset($_POST[$this->csrf_token_name]);
unset($_COOKIE[$this->csrf_cookie_name]);
$this->_csrf_set_hash();
$this->csrf_set_cookie();
log_message('debug', "CSRF token verified ");
}
The method assumes that after the post data has been added everything is fine, which is wrong because allows you to try only once with a token, then if you resubmit the form, the cookie token is renewed but not the one from the post(actually in post there's nothing after this step, because they unset it) .
So this can be considered a bug, because it is not logic to work this way, and without extending the Security class to overwrite this method , is useless .
So, a re-writed method would look like so :
Code:
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
//No we don't kill it, because we really want it to work.
//unset($_POST[$this->csrf_token_name]);
//unset($_COOKIE[$this->csrf_cookie_name]);
//$this->_csrf_set_hash();// not such a good ideea.
//$this->csrf_set_cookie();// if we set the cookie again, won't match what we have in post.
log_message('debug', "CSRF token verified ");
}
I think the above will work (not tested) but having in mind that the cookie is renewed when there's no post data and the csrf_hash is generated when the class is initialized, should work .