代码讲一千个单词

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的每个页面创建新会话

最佳答案

如果我正确理解这一点,听起来您正在为每个请求设置令牌。我的猜测是旧页面仍具有旧令牌。在自动删除令牌之前,我将检查令牌是否已设置。

 if (isset($_SESSION['token'])){
    //do nothing
 } else{
   $_SESSION['token'] = md5(rand());
 }


编辑以解决您的问题。

为每个浏览器会话创建一个密钥,而不仅仅是使用一个“令牌”密钥。

$_SESSION[$sessionId] = md5(rand());


诀窍当然是弄清楚什么时候发生,因为如果您不能使用会话,您将真的不知道请求是来自新选项卡还是旧选项卡。您可以使用查询字符串来传递此参数。基本上,所有请求都必须具有此参数,否则您不会将会话与其关联。

例如

http://www.yoursite.com/somepage.php?sessionid=<some generated id>


最终,用户可能会对此感到厌烦,但是我不确定这周围是否有任何办法。

编辑2好的,这是我的想法。安全专家在那里,如果我有这个错误,请随时开除我,就像我在没有专家之前所说的那样,但是看起来我不会在不提出任何建议的情况下摆脱困境;-)

CSFR的问题在于,某些恶意用户Bob可能会在另一个站点上创建一个元素,从而导致Alice的浏览器向其他站点发出请求,并且由于Alice先前已登录并且该信息以Cookie或Alice的形式存储如果通过会话识别,站点将执行该请求,就像Alice曾请求过一样。例如,如果爱丽丝的银行为http://www.mybank.com,则鲍勃可以创建一个论坛帖子,其中包含

<img srg="http://www.mybank.com/transferfunds.php?amount=1000&receiver=Bob" />


爱丽丝的银行会认为她的浏览器是她的请求。要使此攻击成为可行的攻击,必须发生几个关键的事情(这些失败中的任何一个都会导致攻击失败)(这些是了解如何防止它的关键):


爱丽丝必须登录到她的银行站点,以便银行记住她。这可以在Cookie(“记住我”)中或通过会话进行。但是,如果她关闭浏览器(结束会话)或清除cookie,则不会受到威胁,因为银行站点不会识别她并将拒绝该请求。
鲍勃必须能够为请求提供所有必要的参数,否则银行网站将拒绝该请求。


为了在无状态协议(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中。如果他尝试制作指向您的页面之一的链接,则该链接要么包含错误的密钥,要么将不包含任何密钥,您可以拒绝它。 (为公平起见,他有机会正确猜出恰巧查看其代码的特定用户的令牌,但他可能更容易起火。)

无需为令牌分配超时,因为令牌将在关闭浏览器时消失,并且需要在用户访问网站时重新生成。

关于php - PHP session 与AJAX冲突,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/4789489/

10-14 16:17
查看更多