【发布时间】:2014-07-12 04:53:33
【问题描述】:
我使用 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=
有什么想法吗?我已经检查并重新检查,CRSF 令牌在任何地方都正确设置,除了在我的验证回调中的 $token 中。而且它只发生在某些令牌上......
编辑:所以似乎是 base64 编码导致了这个问题(为什么,我不知道)。我换了
$csrfHash = base64_encode(hash('sha256', uniqid(serialize($_SERVER), true), true));
通过
$csrfHash = random_string('sha1');
【问题讨论】:
标签: php forms codeigniter csrf