CSRF令牌未多次验证


CSRF token not validated from times to times

我使用Codeigniter/PHP。我使用CSRF令牌(不是CI原生版本,因为我有自己的表单实现),并且令牌不时不被验证。

CSRF令牌每个会话创建一次:

function create_csrf_token() //If needed, creates a session variable; returns a hash to use for CSRF protection
{
    $CI =& get_instance();
    if($CI->session->userdata('csrfToken')) //the token already exists: use its hash
    {
        $csrfHash = $CI->session->userdata('csrfToken');
    }
    else //no token yet: create session variable + set its hash
    {
        $csrfHash = base64_encode(hash('sha256', uniqid(serialize($_SERVER), true), true));
        $CI->session->set_userdata(array('csrfToken' => $csrfHash));            
    }
    return $csrfHash;
}

它在csrfToken隐藏输入字段中传递给表单,没有问题,htmlspecialchars应用于它(使用urlencode没有区别):

echo '<input type="hidden" name="'.$this->name.'" value="'.htmlspecialchars($this->value).'">';

该字段有一个验证规则verify_csrf:

public function verify_csrf($token)
{
    $CI =& get_instance();
    if($CI->session->userdata('csrfToken') && $CI->session->userdata('csrfToken') == $token) return true;
    else
    {
        $this->set_message('verify_csrf', 'Invalid token');
        return false;
    }
}
这就是事情变得奇怪的地方。有时$token是不正确的,看起来像损坏的数据。下面是几个例子: 误差

:

$CI->session->userdata('csrfToken'): 6cT3O0KTOk7cVlear71lU7KKFlGONt4rS2HjNoSVFRM=(正确)

$token中的值:6cT O0KTOk7cVlear71lU7KKFlG(第4个字符改变且缺少字符串结束)

没有错误:

$CI->session->userdata('csrfToken'): AiAgGqqxTxuCxN7h5HHRtcJjmHJVMRksBYbq6Dx4Kv4=中的值

$token: AiAgGqqxTxuCxN7h5HHRtcJjmHJVMRksBYbq6Dx4Kv4=中的值

任何想法?我已经检查并重新检查了,除了我的验证回调中的$token之外,CRSF令牌在任何地方都是正确设置的。它只发生在某些令牌上…

编辑:所以似乎是base64编码导致了这个问题(为什么,我不知道)。我已经替换了
$csrfHash = base64_encode(hash('sha256', uniqid(serialize($_SERVER), true), true));

$csrfHash = random_string('sha1');

这只是一个大胆的猜测,但它可能是Base64编码和通过HTTP POST提交表单的组合,就像下面描述的那样:

POST Base64编码的PHP数据

解决方案可以是在发布之前urlencode()令牌?

EDIT:解决方案是放弃令牌的base64编码,转而使用普通的sha256哈希作为令牌。

请使用CSRF的配置

你可以打开你的应用/config/config.php文件,并设置如下:

$config['csrf_protection'] = TRUE;

//这将自动生成form_open(params)函数的隐藏字段,因此您不需要每次都这样做。此功能包含在框架工作中。

避免对特定uri的CSRFhttp://ellislab.com/forums/viewthread/182631/