代码说千言万语
page.php文件?ID = 123
<?php
if(is_ajax()){// function that determines whether the request is from ajax (http header stuff)
$_SESSION['token'] = md5(rand());
}
//some ajax request to ajax.php?id=123
?>
ajax.php?ID = 123
<?php
if($_SESSION['token'] == $_GET['token']){
echo 'Tell me this is for reall';
}else{
echo 'Invalid Request';
}
?>
在用户在另一个标签页上打开 page.php?id = 456 之前,每件事情都可以正常工作,ajax会在 page.php上返回'无效请求'?id = 123 如何解决这个冲突?
ps:如果可能的话,我希望每个页面的新会话用于CSRF目的
答案 0 :(得分:4)
如果我理解正确,听起来就像是为每个请求设置了令牌。我的猜测是旧页面仍有旧令牌。我会检查是否在自动吹走之前设置了令牌。
if (isset($_SESSION['token'])){
//do nothing
} else{
$_SESSION['token'] = md5(rand());
}
修改以解决您的问题。
不是仅使用“令牌”的一个键,而是为每个浏览器会话创建一个键。
$_SESSION[$sessionId] = md5(rand());
诀窍当然是找出发生的时间,因为如果你不能使用会话,你真的不知道请求是来自新标签还是旧标签。您可以使用查询字符串来传递此参数。基本上所有请求都必须具有此参数,否则您不会将会话与它们关联。
e.g。
http://www.yoursite.com/somepage.php?sessionid=<some generated id>
最终,用户可能会对此表示不满,但我不确定是否有任何解决方法。
编辑2 好的,这是我对如何做到这一点的想法。安全专家在那里,如果我有这个错误,请随意给我发火焰,就像我之前说的那样,我不是专家,但看起来我不会在没有暗示的情况下摆脱这种情况; - )
CSFR的问题是,某些恶意用户Bob可能会在另一个网站上创建一个元素,导致Alice的浏览器向其他网站发出请求,因为Alice之前已登录并且该信息存储为通过会话识别cookie或Alice,该站点执行请求,就好像Alice已经请求它一样。例如,如果Alice的银行是http://www.mybank.com,那么Bob可以创建一个包含
的论坛帖子<img srg="http://www.mybank.com/transferfunds.php?amount=1000&receiver=Bob" />
爱丽丝的银行会认出她的浏览器提出请求,认为这是她的。有一些关键的事情必须发生(一起,这些失败中的任何一个会导致攻击失败)使这成为可行的攻击(这些是理解如何防止它的关键):
为了在无状态协议(HTTP)之上提供一些“状态”概念,你实际上无法绕过(1)中的风险。除非你让人们总是点击“注销”或关闭他们的窗口等,否则你无法在浏览器或会话中存储信息。但是,您可以防止(2)成为问题。我对此的解决方案(我确信还有很多其他的)是生成一个哈希值,就像你正在做的那样并将它存储在会话中。
例如,
$_SESSION['token'] = md5(rand());
然后,您所做的就是将该令牌附加到所有内部链接。
http://www.mysite.com/secure.php?token=giuwnrefviunslfghahgliuwnvwrgbaasd
你从不将该令牌存储在浏览器内存中:即cookie。提出请求时,在执行任何操作之前,请检查令牌
//note, you'll want to sanitize user input, I'm just being brief
if ($_GET['token'] != $_SESSION['token']){
//User either attempted to enter a link on their own or it's a CSRF attack
header('HTTP/1.1 403 Forbidden');
}else{
//do whatever needs to be done
}
关键是您网站上的所有链接都包含令牌。但是,Bob无法知道该令牌是什么,因为它没有存储在浏览器的cookie中。如果他试图创建一个链接到您的某个页面,它将包含错误的密钥,或者它不包含任何密钥,您可以拒绝它。 (公平地说,他有可能正确猜出碰巧看到他的代码的特定用户的令牌,但他可能更容易爆发火焰。)
没有必要为令牌分配超时,因为当浏览器关闭时令牌将被删除,并且当用户访问站点时需要重新生成令牌。
答案 1 :(得分:1)
你想做什么?我们能看到JavaScript吗?
看起来您将会话令牌设置为随机哈希,然后再进行检查。因此,如果用户打开两次页面,它将再次随机化并使前一个令牌无效。你期待什么行为?
答案 2 :(得分:0)
您需要让每个页面都启动它自己的令牌,否则会发生这种冲突。
<?php
if(is_ajax()){// function that determines whether the request is from ajax (http header stuff)
$page_id = $_GET['id'];
$_SESSION['token'][$page_id] = md5(rand());
}
//some ajax request to ajax.php?id=123
?>
和
<?php
$page_id = $_GET['id'];
if($_SESSION['token'][$page_id] == $_GET['token']){
echo 'This is for real!';
}else{
echo 'Invalid Request';
}
?>
根据您如何实现所有内容,您可能需要更复杂或更专业的内容,但这应该可以帮助您入门。