Php 唯一表单令牌禁用用户的多任务处理
如果我想保护我的站点和用户免受跨站点伪造(CSRF)攻击,我可以生成一个唯一的令牌Php 唯一表单令牌禁用用户的多任务处理,php,forms,token,csrf,csrf-protection,Php,Forms,Token,Csrf,Csrf Protection,如果我想保护我的站点和用户免受跨站点伪造(CSRF)攻击,我可以生成一个唯一的令牌$token=md5(time()*rand)。令牌在隐藏的输入字段echo''中提交并同时存储在会话变量$\u session['token']=$token中 我将检查任何提交的表单上是否存在($\u POST['token']==$\u SESSION['token']),并相应地继续 然而,有些用户可能会同时处理多个任务。这是我在发布本文时正在做的事情 在撰写我的文章时,我打开不同的窗口/选项卡,可能会研究
$token=md5(time()*rand)在有表单的每页上编码>。令牌在隐藏的输入字段echo''中提交
并同时存储在会话变量$\u session['token']=$token中代码>
我将检查任何提交的表单上是否存在($\u POST['token']==$\u SESSION['token'])
,并相应地继续
然而,有些用户可能会同时处理多个任务。这是我在发布本文时正在做的事情
在撰写我的文章时,我打开不同的窗口/选项卡,可能会研究信息或查看有关堆栈溢出的其他问题。堆栈溢出使我可以毫无问题地提交表单
但如果我在我的网站上这样做——也就是说,在撰写帖子/表单的同时浏览其他页面——每次我从我的网站上调出不同的页面时,我的$token
都会重新生成。使我正在处理并最终要提交的表单上的隐藏输入
标记不正确,因为它不再匹配$\u会话['token']
变量,该变量在我访问其他页面时重新生成
有什么好主意可以防止这个问题,或者有什么更好的解决方案可以首先阻止CSRF?
我希望允许我的用户执行多任务,并希望受到CSRF的保护…即使在选项卡和窗口之间,浏览器也应保持正确的会话id。会话id应相同。(应跨浏览器测试危险假设以确保)
根据会话id生成更多应有效的令牌
所以你可以检查一下这样的东西
$tokenCorrect = false;
foreach($_SESSION['tokens'] as $token) {
if ($token !== $_POST['token'])
continue;
$tokenCorrect = true;
}
if ($tokenCorrect == false) {
die(); //
// Maybe log to database ?? but watch if possible Denial of Service because somebody can write your disk/ shared diskspace full with only making fast requests with a invalid CSRF token
}
我也有同样的问题,你说,因为单一的CSRF,它会被替换,除非他们提交最新的页面,但如果你使用阵列w/会话,它应该解决你的问题。另外,你可能想包括一个验证码,我推荐谷歌的Recaptcha
session_start();
function createToken(){
$token = sha1(uniqid(mt_rand(), true));
$_SESSION['Tokens']['Token'][] = $token;
$_SESSION['Tokens']['Time'][] = time() + (10 * 60); #10 min limit
#you can omit/change this if you want to not limit or extend time limit
return $token;
}
function checkToken($token){
clearTokens();
foreach($_SESSION['Tokens']['Token'] as $key => $value){
if($value === $token){
return true;
}
}
return false;
}
function clearTokens(){
foreach($_SESSION['Tokens']['Time'] as $key => $value){
if($value <= time()){
unset($_SESSION['Tokens']['Token'][$key], $_SESSION['Tokens']['Time'][$key]);
#remove last parameter if you aren't using token time limit
}
}
}
我不知道一个令牌是如何阻止这一切的。一个唯一的令牌应该用来阻止CSRF,可以在GET或POST中使用requests@RaymondN:是的,这正是我正在做的,对吗?在我看来,您在$\u会话中存储了1个令牌['token']?@olli令牌如何阻止攻击者将请求嵌入到您的“带令牌的页面”,并获取令牌并发出请求?很好,这是一个好主意!正在生成多个令牌,这些令牌将在一段时间后过期。。。谢谢你给我的小费@奥利:下一步,你可能需要添加类似于recaptcha的内容。我确实在我的网站的某些地方使用recaptcha,通常只在我希望防止暴力攻击的地方使用。。。我想不出一个场景,在这个场景中,暴力使用令牌进行CSRF是现实可行的…?好主意,谢谢!类的实现更高级,所以我选择它作为最佳答案。。。据我所知,会话ID在浏览器选项卡之间保持不变,因为它是在服务器上生成的(在开始编程之前,我做了一系列测试,以了解一些基本知识)和将用于标识一个用户。关于将在服务器上生成会话,为true,但如果客户端再次请求而没有该会话id,则将在服务器上生成新会话。当新窗口打开时,浏览器可能会拒绝所需的会话id,因此需要对其进行测试,但我知道firefox和IE不会在这里造成问题
<input type="hidden" name="token" value="<?php createToken(); ?>">
if(isset($_POST['token']) && checkToken($_POST['token'])){
#valid token
}else{
#create error message saying that they tried to repost data or session token expired
}