PHPF中的CSRF(跨站点请求伪造)攻击示例和预防

问题描述 投票:48回答:4

我有一个网站,人们可以这样投票:

http://mysite.com/vote/25

这将对项目25进行投票。我想只为注册用户提供此选项,并且只有在他们想要这样做时才可以。现在我知道有人在网站上忙碌,有人给他们这样的链接:

http://mysite.com/vote/30

然后投票将是他在项目上的位置,而他不想这样做。

我读过explanation on the OWASP website,但我真的不明白

这是CSRF的一个例子,我该如何防止这种情况发生。我能想到的最好的事情就是像哈希一样在链接中添加一些内容。但是,在所有链接的末尾添加一些内容会非常恼人。没有其他方法可以做到这一点。

另一件事可能有人可能会给我一些其他的例子,因为该网站对我来说似乎是相当的神话。

php csrf owasp
4个回答
91
投票

如果符合以下条件,这可能成为CSRF的一个例

  • 获取该链接(例如,通过<img>标记):伪造
  • 从另一个站点:跨站点

例如,如果我可以在stackoverflow的HTML源代码中注入这个<img>标记(我可以,因为stackoverflow允许在他的帖子中使用<img>标记):

<img src="http://mysite.com/vote/30" />

你只会投票支持该项目;-)

通常使用的解决方案是在URL中放置生命周期有限的令牌,并在获取URL时检查此令牌是否仍然有效。

基本想法是:

  • 生成页面时: 生成一个唯一的令牌 将其存储在用户的会话中 并将其放在页面的链接中 - 看起来像这样:http://mysite.com/vote/30?token=AZERTYUHQNWGST
  • 调用投票页面时: 检查URL中是否存在令牌 检查它是否存在于用户的会话中 如果不=>不注册投票

这个想法是:

  • 令牌没有很长的使用寿命,很难猜测
  • 这意味着你的攻击者: 只有几分钟的窗口,在此期间他的注射将是有效的 必须善于猜测^^ 必须为每个用户生成不同的页面。

此外,请注意,用户会话离开您的网站后保持活动时间越短,访问不良网站时仍然有效的风险就越小。

但在这里,您必须在安全性和用户友好性之间做出选择......

另一个想法(那不是非常安全,但有助于反对家伙不知道如何强制POST请求),只会在人们投票时接受POST请求:

  • 浏览器正在发送注入标签的GET请求
  • 由于此URL正在修改某些数据,无论如何,它不应该与GET一起使用,而只能与POST一起使用

但请注意,这不是完全安全的:它可能(可能?)可能强制/伪造一个POST请求,有点Javascript。


19
投票

首先,不应该使用GET请求来改变服务器上的状态,因此对于您的投票服务,我建议使用POST / PUT。这只是一个指导方针,但却是一个聪明的方法。

因此,对于您的问题,CSRF是一个客户端问题,因此您使用何种服务器语言并不重要(在您的情况下为PHP)。标准修复是相同的,如下所示:在URI / POST数据中有一个随机值,在Cookie标头中有相同的值。如果这些匹配你可以确定没有CSRF。有关如何在StackOverflow上完成此操作的信息很多,例如。 this one。 祝好运!


5
投票

OWASP有一个用于PHP的CSRFGuard,以及我很久以前为XMB写的ESAPI for PHP - > UltimaBB - > GaiaBB。

http://code.google.com/p/gaiabb-olpc/source/search?q=function+get_new_token&origq=function+get_new_token&btnG=Search+Trunk

似乎其他一些人已经清理了该代码并允许更强的令牌:

https://www.owasp.org/index.php/PHP_CSRF_Guard

谢谢,安德鲁


1
投票

CSRF攻击中有3名玩家

  1. 受害者网站(您的例子中的投票网站)[知道他登录的用户cookie]
  2. 你客户的浏览器(当他登录时)[知道他的饼干]
  3. 攻击者网站[不知道登录用户的cookie]

CSRF攻击取决于2个事实

  1. 浏览器会在每次请求时自动发送cookie
  2. 我们依赖cookie来识别我们的登录用户(例如:setcookie("sessionID", "0123456789ABCDEF", time()+3600);

如果攻击者可以通过离开或其他方式使登录用户请求此操作

// http://victim.website/vote/30

例如,通过将链接放在攻击者网站上或通过电子邮件发送,登录的客户端浏览器将发送识别cookie(sessionID)以及此请求,这将使受害者网站认为他的登录用户真的想要投票!

但是如果受害者的网站更加聪明并且使用额外的GET或POST参数(不是cookie)验证其登录用户的请求,则攻击者现在遇到问题,因为浏览器不会自动发送GET和POST参数,并且他有猜猜看。

// http://victim.website/vote/30?csrfSecret=0123456789ABCDEF

攻击者不知道csrfSecret参数是受害者网站和他的客户端之间的秘密(就像会话令牌一样),因此攻击者无法构建他想要伪造请求的URL。

同样,如果投票是通过POST请求完成的,则攻击者将无法在其网站(或第三方网站)上制作表单,因为他不知道受害者网站与其用户之间的秘密。

<form method="post" action="http://victim.website/vote" >
    <input type="hidden" name="vote" value="30">
    <input type="hidden" name="csrfSecret" value="????? I don't know it :(">
</form>
© www.soinside.com 2019 - 2024. All rights reserved.