我有一个网站,人们可以这样投票:
http://mysite.com/vote/25
这将对第25项进行投票。我想只为注册用户提供此选项,并且只有在他们想要这样做的情况下才能使用。现在我知道有人在网站上忙碌,有人给他们这样的链接:
http://mysite.com/vote/30
然后投票将是他在项目上的位置,而他不想这样做。
我已阅读explanation on the OWASP website,但我并不理解
这是CSRF的一个例子,我该如何防止这种情况发生。我能想到的最好的事情就是像哈希一样在链接中添加一些内容。但是,在所有链接的末尾添加一些内容会非常恼人。没有其他方法可以做到这一点。
另一件事可能有人可能会给我一些其他的例子,因为这个网站对我来说似乎很神奇。
答案 0 :(得分:91)
如果符合以下条件,这可能会成为CSRF的一个例子:
<img>
标记):forgery
例如,如果我可以在stackoverflow 的HTML源代码中注入此<img>
标记(我可以,因为stackoverflow允许在他的帖子中使用<img>
标记) :
<img src="http://mysite.com/vote/30" />
您只需投票支持该项目; - )
通常使用的解决方案是在URL中放置生命周期有限的令牌,并在获取URL时检查此令牌是否仍然有效。
基本理念是:
http://mysite.com/vote/30?token=AZERTYUHQNWGST
有这样的想法:
另请注意,用户会话在离开您的网站后保持活动时间越短,访问不良网站时仍然有效的风险就越小。
但是在这里,您必须在安全性和用户友好性之间做出选择......
另一个想法(这不是非常安全,但有助于反对人们不知道如何强制POST请求),只会在人们投票时接受POST请求:
但请注意,这不是完全安全的:它可能是(可能是?)强制/伪造一个POST请求,只需要一些Javascript。
答案 1 :(得分:18)
首先,不应该使用GET请求来改变服务器上的状态,因此对于您的投票服务,我建议使用POST / PUT。这只是一个指导方针,但却是一个聪明的方法。
因此,对于您的问题,CSRF是一个客户端问题,因此您使用何种服务器语言并不重要(在您的情况下为PHP)。标准修复是相同的,如下所示:在URI / POST数据中有一个随机值,在Cookie标头中有相同的值。如果这些匹配你可以确定没有CSRF。有关如何在StackOverflow上完成此操作的信息很多,例如。 this one。
祝你好运!
答案 2 :(得分:5)
OWASP有一个用于PHP的CSRFGuard和我很久以前为XMB写过的PHP的ESAPI - &gt; UltimaBB - &gt; GaiaBB。
似乎其他一些人已经清理了这些代码并允许更强的代币:
https://www.owasp.org/index.php/PHP_CSRF_Guard
感谢, 安德鲁
答案 3 :(得分:1)
CSRF攻击中有3个玩家
CSRF攻击取决于两个事实
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请求进行的,则攻击者将无法在其网站(或第三方网站)上填写表格,因为他不知道受害者的网站与用户之间的秘密。 / p>
<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>