-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
security: pulling tokens from localStorage is not secure #149
Comments
@kevinburke what is an alternative solution to localStorage? |
Use cookies with the https://auth0.com/docs/security/store-tokens#don-t-store-tokens-in-local-storage |
I just want to paste a quote from a comment that I found in this link https://dev.to/rdegges/please-stop-using-local-storage-1i04 ‘’’ localStorage uses essentially the same security policy as cookies; one of its core principles is that a domain cannot access localStorage data that was created under a different domain so there is no chance that a website could steal data from a different website. Also, httpOnly cookies do not make your site any less vulnerable to XSS attacks; if the attacker manages to inject a malicious script into your front end, then they can use that script to make HTTP requests to your server (directly from the victim's browser) and your precious httpOnly cookie (containing the user's valid session ID) will be attached to every request so the server will service them without suspecting anything. The only real difference is that if the token (e.g. JWT) is in localStorage then the attacker can steal the token to use later (same goes for regular non-httpOnly cookies BTW)... Which is hardly a convenience because it's more advantageous for the attacker to carry-out the attack in-place from the victim's browser rather than from the attacker's own machine (thus allowing their IP to be traced directly). Also, with JWTs, it's good practice to set short expiry dates. If you're using WebSockets you can even issue JWTs with 10 minute expiry (for example) and re-issue a new one automatically every 8 minutes if the user is still connected and logged in; then when the user logs out or becomes disconnected; their last issued JWT will become invalid in only 10 minutes (at which point it becomes completely useless to an attacker). |
If you run third party Javascript on your site or XSS and it gets popped your localStorage tokens are toast. You can reissue a valid cookie every ten minutes, or on every single request if you want, I don't understand why that is an argument in favor of using local storage. Don't listen to me, if you want, listen to OWASP: https://www.owasp.org/index.php/HTML5_Security_Cheat_Sheet#Local_Storage |
This is an important issue and I think the example in the Apollo docs might need to be removed. References (some repeated above):
I've also made a simplified example application that shows this issue in real life: |
@kevinburke Sorry to wake up an old issue, but why would a successful XSS attack care about localStorage and your access token? I am looking to be corrected here, so please go ahead and pick holes: I mean an XSS attack at that point is game over, the environment has already been compromised. What are you actually protecting when XSS compromised, the token? It's irrelevant. You just lost everything else that actually matters: identifying the user of said requests.
cookies (even You can mitigate CSFR attacks by using a CSFR token stored in localstorage combined with the But you're just solving a problem you introduced by using cookies to begin with What I am trying to get at, is that by using cookies you're introducing a problem and then spend time solving it with CSFR tokens. You took time and resources to mitigate a problem you introduced when that should have been spent fixing glaring XSS issues that can happen and hardening your CSP policies. And you're going to have to actually do that, unless you got a controlled environment and not dealing with various browsers in the wild, even from the same vendor.
When XSS attacks happen, cookies won't protect against:
To be clear, I am not making a distinction between a targeted attack or a generic attack that e.g just dumps the content of Application dependent attacks:
Sure you can add password requirements, 2FA and etc. But that's not related. You just compromised your users email & password and cookies didn't help at all except open up other potential vulnerabilities. XSS is game over I am wondering if I am wrong thinking like this or if nonsense like https://dev.to/rdegges/please-stop-using-local-storage-1i04 needs to die. TL;DR |
That response doesn’t make sense, sorry. |
Lol, fine. |
If a malicious js script runs on the client side, (extension, sideloaded or copy+pasted), the attacker can just spoof requests to the endpoint and the cookie will be passed along (as requests coming from same domain). The Secure+HttpOnly cookie vs localStorage is only protecting the auth from being lifted, but a lifted auth is useless in most cases anyways as most systems (worth stealing) check ip + other fingerprints. Example based on @seivan the malicious javascript calls the endpoint to trigger a password reset, (the cookie is already present since its called from the same domain), the user gets a password reset email. The user follows the password reset email, the malicious javascript is loaded on the domain (say the tracking library, PandaTracker, this app uses to track the amount of baby Panda's using the app and gather metrics, got compromised). The user now enters their new password, the malicious JS (having full access to page, pulls the password out the field) sends this password off to the attacker, CORS does not stop writes. Or as @seivan also said, you can just pop up a modal saying, please reenter your password, most users will bite and give up their password. There is a simple 6 step process to having a safe web app.
Bonus: Feel a little safer. |
@kevinburke Please explain why @seivan answer did not make sense. I short answer like this will lead to think that your previous arguments are actually irrelevant now. Also @seivan set effort and time to come with this detailed answer. Please answer to the parts that do not make sense in order to help everyone to understand as well. We all trying to figure out this war of local storage vs cookies in order to secure our apps! |
@Jonatthu I spend a whole day reading about this! This is how if found this issue. I will agree with @seivan that
Storing token in httpOnly cookie may raise the bar of safety but after XSS there will be no rescue. The safest way is to keep the token in memory and ask the user to login after each page refresh. If you want to have a better UX, then just keep the token in localStorage and make your best to prevent XSS. |
One example of a threat vector that HTTP-Only cookies solves compared to XSS is an NPM supply chain attack. A malicious dependency could exfiltrate and POST the entire contents of localStorage for examination later. That's a bigger threat than a malicious dependency publishing a targeted attack on your site (eg hitting the /users/me endpoint to see if that exists) Agree that XSS attacks are to be avoided at all cost. But using a cookie can mitigate their impact while preserving the positive UX of persistent logins. |
You still got malicious code running. Can't this be prevented with CSP to begin with?
Again, this is just security by obfuscation with extra steps. It it's absolutely(!) true that the surface is much smaller, and easier to just dump local storage. In a generic attack where the attack just dumps local storage to a third party service is not protected by a cookie, it's protected by the concept of the malicious code being generic. But then you ask, can't attacker look at your client side code and figure it out?
|
The documentation for header authentication says:
This is not secure. Any other Javascript running on the page (not to mention attackers using a 'learn who is visiting your profile page by pasting this code into the console!' attack) can read a token out of localStorage and do whatever it wants with it, and as far as I can tell, it's pretty common for people to run a lot of third party Javascript on their website.
The documentation recommending
localStorage
should at the very least mention this.The text was updated successfully, but these errors were encountered: