Friday, 5 May 2017

Evil Session Tokens

So we build a new web application, SIMPLES.COM.  Clients login, over HTTPS of course, and a session token is issued.  Since we don't want the client to have to log in frequently, we give the token a long lifetime, or at least a way of using it to get a new one.

The application will have to persist the token on the browser, so cookies are used.  We consider using browser local storage, but cookies seemed the best way to guarantee wide browser compatibility.

The application then validates every HTTP operation, using the session token in the cookie, and authorises access as appropriate.


Enter the hacker.

Client Joe Bloggs receives an email with a phishing link to dodgy website S1MPLES.COM (note the name is different), and clicks on it.  Joe is taken to a page where a few sneaky GET requests are sent to the real SIMPLES.COM website, and Joe's browser helpfully supplies the session cookie, since it's the correct domain, and the hacker now has access to Joe's data.

How do we fix this?

The first thing to do is not use cookies for authentication.  The web app must attach a session token header to each request.  That way the above Cross-site Request Forgery attack is not possible.

However, we now have a long-lived session token being passed around, but that's OK, because we use HTTPS.

Except we don't.  Not all the time.

SIMPLES.COM is accessible over HTTP.  Only the login page and secure site are via HTTPS.

So Joe, being a lover of coffee, and free WiFi, gets caught by a man-in-the-middle attack by Mr Evil with a portable WiFi router.  Mr Evil intercepts the requests, and the session session token sent with each request.

Mr Evil now has full access to Joe's account, for a long time.

The answer is to make SIMPLES.COM full HTTPS, and to use HSTS to ensure no opportunity for man-in-the-middle exists. And to add all the recommended security headers, e.g. content security policy.

Cool.  Mr Evil shrugs, and picks on someone else.

Much later, Mr Bored Developer is browsing through the application logs (helpfully made available via a log aggregator), when he notices that the session tokens are logged for all to see.

Not so cool.

So what do we do?

One way is to use an OAuth approach to issue not one session token, but two: a short-lived access token, and a long-lived refresh token.  The refresh token is stored in the application browser,  but is never used for access, only to request new access tokens.

Of course these access tokens could still be leaked, but being short-lived, should expire very quickly.

Much better.

P.S. Please, please don't build your own security solutions!  Spring Security and mature open source identity and access management systems such as OpenAM are a much better way to go.



Post a Comment