I have an action in my site:
http://mysite.com/User/Logout
This will log the current user out of his/her session. Since this is a simple GET request, a malicious user could either create links to this page or even put this link in an image's src
attribute that would force users to get logged out. I would still like to maintain the simplicity of the logout link without having to go too far, but at the same time I would like to be able to prevent the above scenario from occurring.
Any ideas?
Well, there are a few options that you can do to help secure against CSRF attacks:
Use a form and a random token. So instead of having a "link", use a random token that's set in the session into a form
<form action="/User/logout" method="post">
<submit name="logout" value="Logout" />
<input type="hidden" name="token" value="<?php echo getSessionToken(); ?>" />
</form>
Note that POST is best for this type of action, but you could change the form to a GET without too much trouble.
Then in php, just do:
if (getSessionToken(true) != $_POST['token']) {
die('CSRF!');
}
Note that getSessionToken
should work something like this:
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;
}
Also note that whenever you fetch the token to check it, you should reset it to something new (which is what this does). This prevents replay attacks where an attacker detects the token on submission and resubmits the value.
If you must use a link, then embed the token in the link. But note that this is more susceptible to attack since there's a chance the user might copy and paste the link to someone else. As long as it's a self-resetting token, there shouldn't be much issue with multiple tabs. But realize that it's not optimum:
<a href="/User/logout?token=<?php echo getSessionToken(); ?>">Logout</a>
It's absolutely better than nothing. But I would still suggest using the form for the best protection.
I would highly suggest reading and following the OWASP CSRF Guidelines for preventing CSRF. It will tell you just about all you need to know, and why...