Sco*_*ott 5 php security xss csrf csrf-protection
我在我的网站上有一个动作:
http://mysite.com/User/Logout
Run Code Online (Sandbox Code Playgroud)
这将使当前用户退出他/她的会话.由于这是一个简单的GET请求,恶意用户可以创建指向此页面的链接,甚至可以将此链接放在图像的src属性中,这会强制用户注销.我仍然希望保持注销链接的简单性而不必走得太远,但同时我希望能够防止上述情况发生.
有任何想法吗?
如果您使用GET请求将人员记录下来(或者做比使用GET请求更重要的事情),那么您的网站将容易受到跨站点请求伪造攻击.您应该使用POST注销人员.GET仅用于幂等操作,请参阅RFC 2616第9.1节.
请记住,虽然在这种情况下使用GET不符合RFC,但并不是您需要更改以防止XSRF.有关优秀的解释,请参阅ircmaxell的回答.
那么,您可以采取一些选项来帮助抵御CSRF攻击:
使用表单和随机令牌.因此,不要使用"链接",而是将会话中设置的随机标记用于表单
<form action="/User/logout" method="post">
<submit name="logout" value="Logout" />
<input type="hidden" name="token" value="<?php echo getSessionToken(); ?>" />
</form>
Run Code Online (Sandbox Code Playgroud)
请注意,POST最适合此类操作,但您可以将表单更改为GET而不会有太多麻烦.
然后在PHP中,只需:
if (getSessionToken(true) != $_POST['token']) {
die('CSRF!');
}
Run Code Online (Sandbox Code Playgroud)
请注意,getSessionToken应该像这样工作:
function getSessionToken($reset = false) {
if (!isset($_SESSION['random_token'])) {
$_SESSION['random_token'] = sha1(uniqid(mt_rand(), true));
}
$token = $_SESSION['random_token'];
if ($reset) {
unset($_SESSION['random_token']);
}
return $token;
}
Run Code Online (Sandbox Code Playgroud)
另请注意,每当您获取令牌以进行检查时,您应该将其重置为新的(这就是它的作用).这可以防止攻击者在提交时检测到令牌并重新提交值的重放攻击.
如果必须使用链接,则将令牌嵌入链接中.但请注意,这更容易受到攻击,因为用户可能会将链接复制并粘贴给其他人.只要它是一个自动重置令牌,多个选项卡就不会有太多问题.但要意识到这不是最佳的:
<a href="/User/logout?token=<?php echo getSessionToken(); ?>">Logout</a>
Run Code Online (Sandbox Code Playgroud)
这绝对比什么都好.但我仍然建议使用该表格以获得最佳保护.
我强烈建议阅读并遵循OWASP CSRF指南以防止CSRF.它会告诉你几乎所有你需要知道的,以及为什么......