top | item 2663293

Ask HN: Best Approaches to Prevent Session Hijacking?

7 points| espeed | 14 years ago | reply

I have been looking at ways to guard against session-hijacking, where someone steals a session cookie and uses it to gain access to the system.

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?

10 comments

order
[+] dstein|14 years ago|reply
One trick I read while writing some session code is to generate a session fingerprint using a salted md5 of the IP address + the User-Agent. That adds one extra level of protection in case your session storage (but not your webserver) is comprimised. If an attacker can spoof IP's, and knows the user-agents, then there is no safety except SSL. A post-modern alternative would be to open a websocket and do all communication through it.

See http://stackoverflow.com/questions/616545/php-sessions-usera...

[+] SHOwnsYou|14 years ago|reply
If I'm understanding this right, if a user stays on a single page for longer than 30 seconds, their session is invalidated? That sounds pretty harsh.

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
No, they can be gone for any length of time.

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
The solutions mentioning IP addresses won't solve the problem. For someone to use firesheep to steal session keys, they have to be on the same network, such as a coffee shop's wifi. Your website will see any request from that network as the same IP address.

this solution will not stop the attacker until he leaves the coffee shop.

[+] JoachimSchipper|14 years ago|reply
I'm a bit confused by your threat model - you use SSL but the attacker is able to get your webserver to output arbitrary data? Most web applications that can be persuaded to output arbitrary data can also be persuaded to, say, output the entire database - and no amount of session cookie trickery is going to help you there...
[+] adyus|14 years ago|reply
How about checking the logged user's IP address on each page refresh and storing it on the server, and if there's more than one IP for the same user, invalidate the session?
[+] espeed|14 years ago|reply
Yes, that's a good tactic and worth doing, but IP addresses can be spoofed.
[+] pewpew|14 years ago|reply
You need to consider that many users toady have iphones/ipads. session store will work only once and will require the user to relog each time.
[+] espeed|14 years ago|reply
Why aren't cookies updated on iphones?