October 26, 2010

Protect the flock (or how to mitigate the effects of HTTP session hijacking without using SSL)

So this thing called Firesheep is making a splash the past couple of days. It's a Firefox plugin that lets you hijack HTTP sessions on open WiFi networks (which presumably are NATed, hence trying to use the client IP address as extra authentication doesn't work).

It's possible to mitigate the scope of this kind of session hijacking significantly without resorting to tricks that break the back button. A note about what "mitigate" means here: we're on an open network, so any traffic from the server to the client can be spied on, and since we don't want to break the back button by using one-time information, any GET request that is made by the client can be spied on and repeated by the hijacker. However, the hijacker won't be able to make GET requests to URLs that she hasn't yet spied on, and will be unable to make POST requests.

So how does this work? I'm assuming the initial login is done over HTTPS, during which time the server sends the client a shared secret that the client then stores locally (window.name, Flash LSO, or localStorage). When a client wants to GET a URL, she rewrites it (this can be done using JavaScript on onload, for example) with a query parameter that is a hash (SHA1 in JavaScript, for example) of the secret concatenated with the URL. The server then verifies the hash before responding to the request. POST requests are handled by performing the same hashing on unique server-generated form identifiers (you're already using these to prevent duplicate form submissions, right?).

That wasn't so hard. Let me know if you see any problems with this scheme, or know of a better way.

1 comment:

Christian Ress said...

Good idea. It's usually called a message authentication code and is in fact used by Amazon AWS to sign every request you make to their service.

Important note though: SHA1 is not enough, you will need a function like HMAC to make sure no one alters your message and then recalculates the hash - just using a shared secret is not enough. (read why)