PHP CSRF 令牌代码。安全性足够吗?
最近,我尽了最大努力保护我的网站免受 XSS 侵害,现在我正在防范 CSRF,在观看和阅读了一些有关此事的文章后,我创建了以下代码。
我想知道我的实现在数据库中使用字符串来帮助安全是否正确。我应该做些什么不同的事情吗?我应该检查双方的数据库吗?
代码:
if(!isset($_SESSION['register_token'])){
$keytype = 'register';
$getregisterkey = mysql_query("SELECT key FROM tokenkeys WHERE type='".$keytype."' ") or die(mysql_error());
while ($row = mysql_fetch_array($getregisterkey))
{
$registerkey = mysql_real_escape_string($row['key']);
};
$_SESSION['register_token']=sha1(uniqid(rand(), TRUE).$registerkey);
$_SESSION['register_token_time']=time();
}
<input type="hidden" name="token" value="<?php echo $_SESSION['register_token'];?>" />
if($_POST['register_token']==$_SESSION['register_token']){
$register_token_age=time()-$_SESSION['register_token_time'];
if($register_token_age=>300){
//process form
} else{
//valid token but expired
}
} else{
die('Access Forbidden')
}
Having recently protected my site the best I can against XSS I am now in the process of protecting against CSRF, having watched and read some articles on the matter I have created the below code.
I would like to know whether my implementation is correct in using a string in the database to help security. Is the anything I should be doing differently?? Should I be checking the database on both sides???
Code:
if(!isset($_SESSION['register_token'])){
$keytype = 'register';
$getregisterkey = mysql_query("SELECT key FROM tokenkeys WHERE type='".$keytype."' ") or die(mysql_error());
while ($row = mysql_fetch_array($getregisterkey))
{
$registerkey = mysql_real_escape_string($row['key']);
};
$_SESSION['register_token']=sha1(uniqid(rand(), TRUE).$registerkey);
$_SESSION['register_token_time']=time();
}
<input type="hidden" name="token" value="<?php echo $_SESSION['register_token'];?>" />
if($_POST['register_token']==$_SESSION['register_token']){
$register_token_age=time()-$_SESSION['register_token_time'];
if($register_token_age=>300){
//process form
} else{
//valid token but expired
}
} else{
die('Access Forbidden')
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
XSRF 令牌的安全性取决于发送页面的通道。在此表单上使用
https
并且仅使用https
,并且仅将其提交到https
端点。否则,MITM 可以在提供或提交表单时从表单中获取您的 XSRF 令牌。当有零行时永远不会执行,这种情况下,当您稍后这样做时,您不会从
$getregisterkey
获得太多熵,如果返回零行,我将确保您的实现快速失败。也许更改为
if ($row = mysql_fetch_array(...)) { ... } else { /* abort */ }
因为您无法从额外的行中获得任何好处。rand()
必须是真正随机的或加密强度高 PRNG。我不熟悉 PHP 的标准库,但 [wikipedia] 表明
rand()
的加密强度不高。 维基百科说PHP 中的强加密 建议使用
openssl_random_pseudo_bytes()< /代码>
如果您使用弱随机性,那么攻击者可以观察您生成的数字(通过请求多个版本的表单并解析隐藏的输入)并使用它来找出下一个数字可能是什么并伪造 CSRF 令牌。
如果攻击者修改
'register_token_time'
会话属性,那么他们就可以避开您的 XSRF 检查。例如,如果您有一个页面这样做
,那么攻击者可以通过 POST
来替换会话中存储的 register_token,然后发送带有 XSRF 保护的帖子
并绕过您的 XSRF 保护。
XSRF tokens are only as safe as the channel over which the page is sent. Use
https
and onlyhttps
on this form and only submit it to anhttps
endpoint. Otherwise a MITM can get your XSRF token from the form as it is served, or as it is submitted.will never execute when there are zero rows which case you don't get much entropy from
$getregisterkey
when you later doso I would make sure that your implementation fails-fast if there are zero rows returned. Maybe change to
if ($row = mysql_fetch_array(...)) { ... } else { /* abort */ }
since you get no benefit from extra rows.The
rand()
needs to be either truly random or a cryptographically strong PRNG.I am not familiar with PHP's standard libraries but [wikipedia] suggests
rand()
is not cryptographically strong. wikipedia saysStrong cryptography in PHP suggests using
openssl_random_pseudo_bytes()
If you use weak randomness then an attacker can observe the numbers you generate (by requesting multiple version of the form and parsing out the hidden input) and use that to figure out what the next numbers might be and forge CSRF tokens.
If an attacker modify the
'register_token_time'
session property then they can avoid your XSRF checks.For example, if you have a page that does
then an attacker can POST
to replace the register_token stored in the session and then send a post with
and bypass your XSRF protection.