Ask HN: Best Approaches to Prevent Session Hijacking?
Programs such as http://codebutler.com/firesheep make it easy to sniff sessions on open Wireless networks, and other ways of getting sessions include cross-site scripting attacks, or just physically lifting them from a victim's computer.
Using SSL to secure all session-cookie/server communications is critical for preventing the Firesheep sniff, and setting HTTPOnly on the cookie helps prevent JavaScript from being able to read the session cookie in XSS attacks, but it's still vulnerable to AJAX-based attacks.
Another layer is to include a security token or a nonce in the session cookie that gets updated on each request. You store the token in a server-side datastore and in the cookie, and on each request you compare that the token in the cookie matches the token in the datastore.
If the tokens don't match that could be an indicator that someone stole the session and is trying to use it so you can either ignore the request or invalidate the session and require the user to re-authenticate. However, mismatched tokens could also result from a slow/flaky connection.
For example, you could have a case where the server receives a request from a real user, updates the session token in the server datastore and responds to the user with a session cookie that contains the updated token. But the user doesn't receive the response due to a slow/flaky connection so the user still has the old session token while the new one is stored on the server. When the user retries the request, the tokens won't match.
One way to mitigate this problem is for the sever to keep a history of the last few tokens and check that to see if they match, but then it becomes a situation of how many tokens to keep, and depending on how flaky the connection is or how click-happy the user is, the server may cycle through the history before the connection comes back and the user's session gets updated by the browser.
An alternative to keeping a token history is to timestamp each session and check if the timestamps are within some short, specified range, say 30 seconds. If the user's session cookie timestamp is within 30 seconds of the server's stored session timestamp, then the session is deemed authentic.
Example pseudocode
def authenticate_request():
if (stored_session.timestamp - session.timestamp > 30 seconds):
return False
return True
This avoids having to keep a token history -- the timestamp becomes the token -- but attackers have a 30 second window of opportunity to hijack the session after it's stolen. While this is true, the token-history alternative isn't any better because it gives attackers a potentially longer window of opportunity.Other approaches of checking for IP address and User-Agent changes have issues too. User Agents are easily spoofed, and if an attacker is able to get a user's session, they can easily determine the User Agent through the same XSS code or some other means.
If the user is on a mobile device, their IP address may change frequently so that would result in many false positives. Furthermore, the attacker could be behind the same company firewall so the user and attacker's IP are the same to the external Web server.
Is using a timestamp token the right approach or is there a better way? Is the 30-second buffer about right? What edge cases am I missing?
[+] [-] dstein|14 years ago|reply
See http://stackoverflow.com/questions/616545/php-sessions-usera...
[+] [-] unknown|14 years ago|reply
[deleted]
[+] [-] SHOwnsYou|14 years ago|reply
I typically concatenate the users IP and UserAgent. If the new request doesn't match, the session is invalidated and they need to log in again -- But I also don't have a mobile offering for many of the sites I build, so the changing IPs problem is mitigated substantially.
[+] [-] espeed|14 years ago|reply
Think of the timestamp stored on the session cookie as a token -- as long as it matches the token on the server it doesn't matter how long the token sits on the user's computer until their next request, it just has to match.
The 30-second window is just to reduce false positives from an active user double clicking on a slow/flaky connection. Under the normal case of a matching token, the difference between (stored_session.timestamp - session.timestamp) will equal zero (no difference).
[+] [-] badkins|14 years ago|reply
this solution will not stop the attacker until he leaves the coffee shop.
[+] [-] JoachimSchipper|14 years ago|reply
[+] [-] espeed|14 years ago|reply
1. Cross-site scripting (XSS -http://en.wikipedia.org/wiki/Cross-site_scripting)
2. Cross-site forgery (http://en.wikipedia.org/wiki/Cross-site_request_forgery)
It doesn't necessarily mean the attacker has compromised the server, but they may have been able to post code to a page, e.g. through a form posting.
[+] [-] adyus|14 years ago|reply
[+] [-] espeed|14 years ago|reply
[+] [-] pewpew|14 years ago|reply
[+] [-] espeed|14 years ago|reply