我想使用令牌来防止我网站上的CSRF攻击(用PHP编写)。我已经在表格中使用它并且效果很好。但注销链接不是表单;它只是一个超链接 如果我将令牌放在查询字符串中是否安全,如下所示:
<a href="logout.php?token=9ae328eea8a72172a2426131a6a41adb">Logout</a>
如果有任何问题,您的建议和解决方案是什么?
答案 0 :(得分:4)
是的,如果,则CSRF令牌是不可取的&#39;并验证:两种情况下的方法都相同。
来自维基百科的Cross-site Request Forgery - Prevention:
网站提供各种CSRF对策。在所有表格提交和副作用网址中要求提供特定于用户的秘密令牌,以防止CSRF;攻击者的网站无法在提交的内容中加入正确的令牌。
如果令牌来自表单值或查询字符串参数 1 ,则无关紧要。通过在表单中包含令牌来阻止CSRF的方法适用于(并且有效)超链接 2 。
1 可以拦截URL的MitM /代理可以轻松拦截HTML表单。这超出了标准CSRF攻击或缓解此类攻击的范围。在这种情况下,CSRF令牌值是可识别的&#39;并且系统不安全。
2 这假设令牌是每用户(和时间敏感)值。在大多数情况下,会话ID的简单HMAC哈希就足够了。
答案 1 :(得分:4)
我认为在GET请求中使用CSRF-token的一个主要缺点是,无能的用户可能通过复制带有令牌的链接并将其粘贴到某些公共内容(如评论/帖子/等)中来轻松披露其令牌。还有GET查询参数,包括通常由HTTP服务器/代理记录的CSRF令牌,它会带来另一种风险。
所以我建议您使用以下内容实现CSRF安全链接:
<form name="logout" action="logout.php" method="post">
<input type="hidden" name="token" value="9ae328eea8a72172a2426131a6a41adb"/>
</form>
...
<a href="/nojs.html" onclick="document.logout.submit(); return false">Logout</a>
答案 2 :(得分:0)
其他人提出了一些好处。我添加这个答案来增强他们的作用。 始终过滤并验证查询字符串名称/值对。
给定:您有一个数据库,并且您想要创建一个链接来帮助动态获取(但不能更改)用户可以链接到的内容。示例:新闻文章,案例研究,公共用户档案。
要求:使用查询字符串并使用令牌阻止CSRF。
CSRF令牌的目的之一是帮助验证从您的域提供的页面生成传入的HTTP请求(无论会话是否在进行中。会话令牌是一个单独的野兽)。当您使用多个防御向量时,CSRF令牌最有效。
比较:检查提交的令牌是否与会话中的一个匹配。
时间:您可以指定令牌仅适用于未来某段时间。
public function setFormToken()
{
$token = $this->cipher->getFormToken(); //Some hashing algorithm.
$this->formToken = $token; //In this example, used to insert the token into HTML.
$_SESSION['token'] = $token; //Save the token for comparison upon form submission / HTTP query string processing.
$_SESSION['tokenExpireTime'] = time() + (60 * FORM_TOKEN_EXPIRE_MINUTES); //This is just an abstract example.
return;
}
然后,除了将提交的令牌与会话中的令牌进行比较外,还要验证提交期限是否仍然有效。
private function hasTokenTimeLeft()
{
if(isset($_SESSION['tokenExpireTime']) && (time() < $_SESSION['tokenExpireTime']))
{
return true;
}
throw new SecurityException("Token time has expired for this POST request.", 911);
}
会话:如果会话已过期或不存在,则内容的错误HTTP请求将失败。
请求信息:使用HTTP POST请求,有些人尝试检查令牌,用户代理和IP 是否与原始HTTP GET请求中的匹配(这意味着在响应GET请求之前将其存储在会话中。)
如前所述,查询字符串可以缓存。无论如何,如果数据应该公开可用,那就没有问题。想想有人在电子商务网站上为产品添加书签。
你要问自己的是&#34; 我是否可以随时随地通过带有查询字符串的链接来获取此内容?&#34;如果是,请不要使用真实的后端,随机生成的CSRF令牌。想象一下,你是通过口口相传奔向民选办公室,人们通过电子邮件向他们的朋友和家人发送链接(好的,不好的做法)。在这种情况下,你永远不想出发一条&#34;绊线&#34;并导致失败的情况。如果始终需要在后端生成新的令牌,则通过电子邮件发送链接将无效。
如果您无法从安全上下文之外(即登录前)获取内容,那么您可以自由采取任何必要措施来使用查询字符串来强化CSRF令牌策略< / em>的
您的退出代码段就是一个很好的例子。
<a href="logout.php?token=9ae328eea8a72172a2426131a6a41adb">Logout</a>
安全上下文之外的任何人都不能使用注销功能。你想要&#34;旅行线&#34;如果有人通过电子邮件发送此链接!显然,会话已集成到此解决方案中(在用户使用页面时,必须将令牌存储在某处)。应该仔细管理会话持续时间和注销,我说你做得很好。
加密:您唯一能做得更好的是加密查询字符串的哈希/令牌,然后解密并在提交时验证它。此外,您可以将令牌分解成碎片,混合碎片,并基本上使用隐藏字符串技术的一些安全性来使您的CSRF令牌更具弹性。