题
我有一个网站,人们可以这样投票:
http://mysite.com/vote/25
这将对项目 25 进行投票。我只想让注册用户可以使用此功能,并且仅当他们想要这样做时才可用。现在我知道当有人在网站上忙碌时,有人给他们一个像这样的链接:
http://mysite.com/vote/30
那么他就可以对该项目进行投票,而他并不想这样做。
我已阅读 OWASP 网站上的说明, ,但我不太明白
这是 CSRF 的一个例子吗?我该如何防止这种情况发生?我能想到的最好的办法就是在链接中添加一些东西,比如哈希值。但是在所有链接的末尾添加一些东西会非常令人恼火。难道就没有其他办法可以做到这一点吗?
另一件事可能有人可以给我一些其他的例子,因为这个网站对我来说似乎相当模糊。
解决方案
如果满足以下条件,这可能成为 CSRF 的示例:
- 该链接已获取 (通过
<img>
标签,例如) :伪造 - 来自另一个网站:跨站点
例如,如果我可以注入这个 <img>
stackoverflow 的 HTML 源代码中的标签 (我可以,因为 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 一起使用
但请注意,这并不完全安全:它是 (大概 ?) 可以使用一些 Javascript 来强制/伪造 POST 请求。
其他提示
首先,GET请求不应该被用于改变状态的服务器上,这样的投票服务,我会建议POST / PUT。这只是一个指南,但一个聪明的一个。
所以你的问题,CSRF是一个客户端问题,所以没关系样的服务器语言,你(你的情况PHP)使用什么。标准解决方法是相同的,并且是这样的:有在URI / POST数据的随机值,并在Cookie头部的值相同。如果这些比赛,你可以肯定没有CSRF。有一个关于如何在这里可以在计算器上就做出大量的信息。 这个。结果 祝你好运!
OWASP对PHP一个CSRFGuard,并为ESAPI PHP,我写了一个很久以前的XMB - > UltimaBB - > GaiaBB。
看来一些其他人已经清理的代码并允许更强的令牌:
https://www.owasp.org/index.php/PHP_CSRF_Guard
感谢, 安德鲁
CSRF 攻击中有 3 名玩家
- 受害者网站(您的示例中的投票网站)[知道他登录的用户cookie]
- 你客户的 浏览器 (当他登录时)[知道他的饼干]
- 攻击者网站[不知道登录用户的cookie]
CSRF 攻击取决于 2 个事实
- 浏览器会根据每个请求自动发送 cookie
- 我们依靠 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>