DEV Community

Discussion on: What Happens If Your JWT Is Stolen?

Collapse
 
kspeakman profile image
Kasey Speakman • Edited

Thanks for the article. It is a great explanation of JWT ins and outs.

I had a couple of points of note from the article. And I wanted to see what you thought.

You mentioned MITM and client or server access (assuming physical or remote computer access), but using HttpOnly cookies does not help there either -- the attacker can still access them through the network traffic or OS respectively.

The main advantage of HttpOnly cookies vs local storage is in the case of js-based malware injection. (As if I needed another reason to run an ad blocker.) The advantage is that HttpOnly cookies are resistant to JS-based exfil, but local storage data is not. However, if the attacker has compromised the client app, they can still use the HttpOnly cookie from the client (XMLHttpRequest/Fetch with "credentials") to attack the API even without being able to see the contents of the cookie. As a bonus, the attack is literally coming from the user's browser, masking the attack/er.

The exfil weakness can be mitigated using CSP. It is good practice to use CSP anyway, since it can block other attacks which use external servers. However, I grant that CSP is not the most friendly thing to setup.

But probably, an attacker will try to get your OS compromised via exploit rather than trying to muck about with JS.

Disclosure: I use JWT from local storage, so obviously I don't rate the risk as highly as you do. (And the only external script I include is the one from my auth provider.) However, I am considering redirecting post auth tokens to an API endpoint to turn the token into an HttpOnly cookie for the browser. Being that it would just be a perfunctory "receive token and stuff into a cookie", it does not have any statefulness to drag down perf/scalability. And ultimately it is still signature-verified by the server before processing requests. Assuming appropriate CORS origin restrictions to mitigate XSRF. What do you think?

Collapse
 
vicxxx profile image
VicXXX

See I do the same although I use cookies to store as I need to be able to share token on multiple subdomains (don't ask me why just have to). The article is a little bit misleading in terms of what is the impact of someone hijacking your JWT token. Technically if they have compromised your machine they pretty much hold you by the short and curlies and can access far more sensitive data than your JWT token.

Collapse
 
rdegges profile image
Randall Degges

Hey! You might enjoy this talk I've given on the cross-domain stuff: youtube.com/watch?v=pYeekwv3vC4 I cover using cookies with cross-domain and the proper way to do it towards the middle of the talk.

Thread Thread
 
vicxxx profile image
VicXXX

Cheers! I'll have a look.

Thread Thread
 
vicxxx profile image
VicXXX

Hahhaa I like how it's called JSON Web Tokens Suck... I kinda agree :D

Collapse
 
kspeakman profile image
Kasey Speakman

Oh I totally understand needing to be able to share the token across subdomains. It helps with deployment flexibility.

One note of caution though. I realized later that what I described at the end (putting the JWT in a cookie) opens itself up to XSRF attacks unless other precautions are taken. Common ones are anti-forgery tokens (which requires keeping some session state) or using CORS with appropriate Origin restrictions.

Thread Thread
 
vicxxx profile image
VicXXX

Yeah we do that already and actually upgrading platform to stop relying on the client generated cookies and switching to http only

Collapse
 
rdegges profile image
Randall Degges

Heyo! Great comment.

I guess here are my overall thoughts on the subject: XSS (where an attacker can execute JS on your site) is one of the OWASP Top 10 most common exploits for a long time now. It's far more common that desktop or server compromise by a massive factor.

Because of this, I tend to dislike relying on browser storage (local storage or whatever) to store sensitive data. Part of the reason why is that if you have a token in local storage an attacker can compromise it and send it off to whatever API they run to harvest your data.

Attackers can then remotely performing attacks against your service impersonating a user, OR, if they want, they can simply fire off requests from the browser using the JWT against your backend service and still cause problems.

Compare this to the alternate scenario: if your session is managed via an httpOnly cookie. In this case, even if an attacker can gain JS access they can only make authenticated requests against your site while the user is ON THE SITE doing stuff. They won't have access to a token they can harvest which they can use while you (the user) are offline or whatever.

Because of this, the latter option is a lot nicer to me in terms of web security. But, again, like everything in the security world: context matters.

If you're building simple sites where there isn't a lot of super important data/etc., and you really like using tokens (even though it's far simpler to use httpOnly cookies in just about every web framework) -- go for it :o

Collapse
 
kspeakman profile image
Kasey Speakman • Edited

I watched your video. You are certainly right about cookies being the more secure storage option. It's just too bad that the constraints on cookies make them hard to use universally, especially for stateless purposes.

You are missing a very large point about scalability of sessions vs stateless. Your argument is basically "sessions are easy to scale". You are right in that it has been done and is understood. But the argument for stateless is "there is nothing to scale". There is no extra DB (with an external provider), no added request latency, no caches to invalidate, etc. A lot of overhead and operational complexity is just gone.

However, there is a trade-off for how "instant" your security changes take effect. For stateless, changes won't take effect until the token expires. If it is critical for your app that security changes are immediate, then there is no benefit to going "stateless"... it will end up with at least the same level of complication as session based but with less benefit. IOW, looking up a blacklist from DB on every request has no different overhead from just looking up user permissions on every request, but the latter has more capabilities (seeing security changes, not just token invalidation). Note that introducing caching into session-based security throws away the immediacy advantage too!

Since you work in security, it makes perfect sense that you see sessions as the best possible implementation. But for many apps, "instant changes" will have little real benefit to the app while the session infrastructure will still eat non-trivial ops budget.

Also for "JWT and mobile", in your video you only mentioned mobile browsers. But I doubt that is the point that people are trying to get across when they say that, since as you said, mobile and desktop browsers aren't that different. The point is that native apps probably don't have built-in automatic cookie storage and retransmission, origin tracking, protected header enforcement, etc. (all the things that make it easier in browsers). So the "cookies are easier" rule doesn't really follow. You could still send them, of course, but it is just as easy to send an Authorization header as a Cookie header, and a lot of people like working with JSON better than form-encoded data (for the stateless case anyway... for sessions you never look at data so it doesn't matter much).

In summary, you are not wrong about what is most secure. But everything is a trade-off. And sometimes trading in some security features (like stateless instead of instant security changes) can gain large benefits in other areas.