14

I'm creating a JWT login mechanism for a site.

There are two very opposing opinions on how to store the JWT. Stormpath swear by cookies httponly: https://stormpath.com/blog/where-to-store-your-jwts-cookies-vs-html5-web-storage Auth0 swear by localStorage: https://auth0.com/blog/cookies-vs-tokens-definitive-guide

At first I sided with Auth0, then with Stormpath, but now I'm back to thinking localStorage is best. The pitfalls of localStorage is an xss attack can capture the JWT, the pitfall of auth0 is an csrf attack can steal the cookie.

It seems like the developer can make the cookie method really difficult for the hacker to gain access through CSRF, but not impossible. However, if the developer users localStorage and manages his codebase and sanitizes his inputs, it seems that the hacker has no way in, is this wrong?

user2331566
  • 143
  • 1
  • 6

3 Answers3

9

The main argument for local storage seems to be this:

it is easier to protect against XSS than protecting against XSRF

The argument for that is that XSS is supposedly solved by automatic input sanitation, while CSRF is difficult to understand.

The second point may or may not be true, but - as your source states - complete protecting against CSRF is relatively simple. If your application is restful it is simply a matter of checking all POST requests for a CSRF token*.

XSS on the other hand is not that simple. Input sanitation is not the solution, encoding the output is. And the problem is that this encoding depends on context. Different encoding is for example needed if you are in a JavaScript or HTML context.

While some frameworks do provide templating engines with automatic encoding, others do not. And automatic encoding generally only HTML encodes, but does not consider XSS in a JavaScript context. Adding to that that many developers skip the templating engines in some cases and output user inputs directly, I would argue that XSS is more difficult to defend against than CSRF.

* This is a bit simplified, and there are other things to consider. HTML injection for example may leak CSRF tokens, and the application may actually use GET requests to change the server state.

Conclusion

I would disagree that XSS is easier to defend against than CSRF. As this is the main argument for local storage, I would go with the cookie approach. It provides small mitigation for XSS and also has the added benefit of ensuring that relevant data is only send over HTTPS (via the secure cookie attribute).

tim
  • 29,018
  • 7
  • 95
  • 119
  • 2
    yes, this is what I also thought at first. However, the first comment on the stormpath article has a very good point - "the attacker can do is inject script that reads your CSRF cookie (which is not HttpOnly) and then make a request to one of your API endpoints using this CSRF token with JWT cookie being sent automatically. So in reality you are still susceptible to XSS, it's just that attacker can't steal you JWT token for later use, but he can still make requests on your users behalf using XSS" doesn't this seem like quite simple way of getting around crsf token? – user2331566 Jan 12 '17 at 14:40
  • 3
    @user2331566 yes, if you have XSS, you automatically have CSRF (this is always true). That's also why I said that httponly provides a "small mitigation". Stealing session data is the easiest way to exploit XSS, but there are many other possibilities (phishing, CSRF, keylogging, etc). – tim Jan 12 '17 at 14:54
  • again, thank you for the answer. Doesn't the localStorage method deny the csrf approach? So, if the site didn't have XSS vulnerabilities wouldn't localStorage make it 100% safe (in terms of xss / xsrf). But using cookie httponly method allows csrf attacks? – user2331566 Jan 12 '17 at 15:11
  • @user2331566 I haven't looked at it in-depth, and it will likely depend on the exact implementation, but yes, local storage seems to provide CSRF protection, so you would basically get it for free (but really, I would probably still add actual CSRF protection, it's not that difficult to implement). But "if the website didn't have XSS vulnerabilities" is a very big "if". Most somewhat complex websites have them or had them in the past. And XSS would of course also allow CSRF with the local storage approach. – tim Jan 12 '17 at 15:26
  • There are such differing opinions of this online. Some people say XSS is pretty much sorted with caja and csrf is the bigger concern going forward. Others say XSS is the biggest concern as this is where most attacks happen. It's really confusing, I've watched several videos / conferences and read articles on xss, but I think I need to get my hands dirty to appreciate this issue. Can you guide me in where I can really get started in understanding this – user2331566 Jan 12 '17 at 15:31
  • @user2331566 from what I understand, caja is basically a sandbox used to safely include third-party code. You wouldn't normally use it to defend against XSS from userinput. Theoretically, XSS is pretty much solved with templating engines that automatically encode, but there you still have the context problem (ie a JS context), so you still need developers that are security-aware. CSRF is a much smaller issue, as you can add general protection to your framework or application of which developers do not need to be aware of. As for resources, sorry, I don't really have any I could recommend. – tim Jan 12 '17 at 15:41
  • would you say, if you have a good csrf protection + cookie httponly, the user session would be completely safe? – user2331566 Jan 12 '17 at 15:45
  • 1
    @user2331566 completely safe is probably an overstatement, but it's the approach I would recommend. – tim Jan 12 '17 at 16:17
5

In my experience as a developer and pen-tester, I would argue that it is probably easier to work with a web development framework that has inbuilt protection against CSRF than it is to have developers correctly protect against XSS. This would suggest Stormpath's solution.

Chances are that you probably want to protect against both attacks anyway.

Colin Cassidy
  • 1,880
  • 11
  • 19
  • 1
    yes, protection for both is essential. For node js, would you have any suggestion in what's best for express? – user2331566 Jan 12 '17 at 15:38
0

Probably using a combination of both is more secure because each store protects you from one form of attack (XSS or CSRF). Here is a nice writeup about the same:

http://www.redotheweb.com/2015/11/09/api-security.html

amit_saxena
  • 151
  • 2