Saturday, December 29, 2007

Logout via Javascript with OnBeforeUnload

One sure fire way to protect users from CSRF attacks is to minimize the window of time that a user is logged in. Current CSRF mitigation strategies focus around the topic of adding a token to each form and link in addition to timing out the session after the the user has been inactive for a relatively short window of time.

However, any third party site than can exploit a weakness in Single Origin Policy can break though these defenses (such as the iframe SOP hack we saw in the past). In addition, the web world is moving to technologies that allow cross-site-requests on purpose, both through Flash, JavaScript and other technologies for mash-up capability.

Not all users are kind enough to explicitly press the logout link or button when they are done using your site. There are three situations that we can trap via JavaScript and force the user to logout without requiring additional action of the part of the user.

1) The user simply types in or browses to a new url in a single-tabbed environment without explicitly logging out.
2) The user closes the tab or window without choosing to press the logout link or button.
3) The user browses to a new tab while staying logged in the previous tab.

The following code sample will allow a programmer to trap events 1) and 2) reliably in IE 6/7 and Firefox 2. It's trivial to fire off the logout event especially if your logout server code will allow a GET request.
<html>
<body onbeforeunload="dothis();">

<script>
function dothis() {
alert('logmeout ajax event');
}
</script>

</body>
</html>
The third situation, when a user changes a browser tab, is much more difficult of an event to trap since it does not fire a onbeforeunload or similar event. It may also harm the user experience. Browser tab changing may not be a situation where the user actually wants to log out. None the less, to accomplish this task, you will need to work with the windows' onblur event. However, this event is very chatty. Just changing a tab will fire onblur event 5 times in Firefox 2.0. You
can play with code such as:

<script>
var logout = false;
function dothis() {
if (logout == false) {
alert('logmeout ajax event');
logout = true;
}
}
</script>

But Firefox 2 will still fire the alert 2x. You will need to test and expand upon this code for each unique browser.

Logging out via JavaScript is by no means a complete CSRF mitigation, but is an excellent defense-in-depth measure to add to your current mitigation strategy.

No comments: