Evil Session Tokens
Tags: security, oauth, web, softwaredevelopment
Published: 2017-05-09 21:18:17

---
title: Evil Session Tokens
published: true
description: How to solve the issue with web session tokens  
tags: security, OAuth, web, software development
---

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

The application persists the token on the browser using cookies.  You did consider using browser local storage, but cookies seemed the best way to guarantee wide browser compatibility.

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

Sorted.


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 potentially has control of Joe's account via a number of [Cross-Site Scripting Attack](https://en.wikipedia.org/wiki/Cross-site_request_forgery) attack vectors.  (*Edited previously incorrect statement about full access, which isn't applicable to this scenario - see comments below*)

How do we fix this?

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

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

Except you 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 in a man-in-the-middle attack by Mr Evil with a cheap, portable WiFi router.  Mr Evil intercepts the requests, and of course 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](https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security) to ensure no opportunity for man-in-the-middle exists. And to add all the recommended security headers, e.g. [content security policy](https://en.wikipedia.org/wiki/Content_Security_Policy).

Cool.  Mr Evil shrugs, and decides to pick on someone who hasn't read this article.

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. Developers are not immune to the lure of crime, even when writing Clojure.

So what do we do?

One way is to use an OAuth-style 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, will expire very quickly.

And there you have it.