Persistent XSS, where the malicious string originates from the website's database.
Related
I am designing a new web application which requires an oAuth2 implementation. I've been reading up on oAuth2 Authorization Code flow with PKCE. That makes sense, it ensures that de client who is initiating the Authorization Code flow is the same client as the one who is exchanging the authorization code for access token (and/or refresh token).
But then I was wondering on how we could deal with refresh tokens. I understand that BFF is now the preferred solution for this, where we use a separate component (Backend for Frontend) that handles all calls from the web app and proxies those to the backend api, all the while handling all access tokens and refresh tokens. The web app and BFF maintain a session cookie, so the BFF can track which access token should be added to which request and so forth.
Most blogs mention something in the lines of "and this is safe if you set the session cookie to strict and http only and secure, because no malicious JS can get that cookie then".
And that is where I have trouble understanding why this is safer. If cookies are safe enough to deal with session id's, then why are they not safe enough to deal with access tokens? Or even refresh tokens? If they are cookie based, then they are sent with each request and no malicious JS can access it. If they could, then the BFF model doesn't provide any additional security, just a little more complexity, no?
So bottomline is: if BFF is deemed safe(r) because the sessions are kept in secure http-only cookies, why is keeping access/refresh tokens in secure http-only cookies not safe?
Adding a BFF to the mix does change the security of using tokens. The BFF is a confidential client so it makes the whole solution more secure, for sure, but this is not the only reason you would use a BFF. One of the main benefits is to keep tokens away from the browser. You don't want the tokens to be accessible by Javascript, that's why you want to rely on cookie-based sessions instead. This protects you from XSS attacks that want to steal the tokens. However, using sessions opens you to CSRF attacks and session-riding attacks. Protecting against CSRF and session-riding should be a bit easier than mitigating XSS as you can become vulnerable to XSS through a third-party library's dependency, for example.
E.g. in case of BFF: steal session from cookie -> make request to BFF -> get access to user data. In case of no BFF: steal AT/RT from cookie -> make request to API -> get access to user data. I still don't understand how this is safer, I am sorry for not understanding it.
You don't have to be sorry! It's good that you're trying to understand that.
The problem with your example is this: you assume that there is no BFF, but AT/RT are kept in cookies. If you're using cookies then it means that you have some sort of a backend component that sits between your SPA and APIs. Otherwise, you would have to deal with tokens in the browser (readable by JS). So the difference that you should be contemplating here is — am I using HTTP-only cookies to call my APIs or do I need tokens and set Authorization headers in JS? For the former case, it doesn't matter if you have a session ID in the cookie or the actual AT. The important part is that JS can't read the content of that cookie.
Another thing is that it's harder to steal sessions than tokens kept in JS. For someone to steal data from cookies you would need a Man-in-the-browser attack. If the tokens are available to JS, then all you need is an XSS attack to steal them.
As I mentioned, using cookies opens you up to CSRF and session-riding attacks, but their impact is limited:
the attacker can only perform an attack when the user has an open session. As soon as the user closes the browser no more data can be stolen (whereas, when an attacker steals a token, they can read data for as long as the token is valid)
the attacker can only perform the same actions that a user can from the front end. This should also be the case for a stolen AT, but in reality, access tokens usually have too broad privileges, and there are APIs you can call with a token that are not normally accessible from the UI.
At Curity we have spent some time researching this and you can have a look at this whitepaper we wrote about the security of SPAs and the pros and cons of different approaches: https://curity.io/resources/documents/single-page-application-security-whitepaper
BFF is considered safer not because of the cookie usage when using the access tokens but because the way of obtaining tokens is more secure. SPAs by definition are not able to keep a secret (in the browser) thus have to use a flow that involves a public client. The BFF allows for a confidential client because the client secret is kept in the backend.
Using PKCE with the public client gives you assurance indeed about the same entity requesting and receiving the tokens, but it give you little assurance about the authenticity of that client. A confidential client takes care of the latter.
Wouldn't a malicious site be able to read the cookie using xss cookie stealing and put it in the header of an ajax request?
Of course, if the site is vulnerable to xss, it's also vulnerable to csrf, but that's the smaller issue then.
If there is no xss though, the attacker has no way to read the token due to the same origin policy.
I'm reading about JWTs and I'm really confused by something which doesn't seem to be addressed:
What is stopping a malicious website from just including
localStorage.get ('secretjwt')
in their code and stealing your tokens?
If you don't store it as a cookie then anyone can access it! And if it stored as a cookie, then why not just use cookies full-on?
Cookies and localStorage are protected by same-origin policy
In computing, the same-origin policy is an important concept in the web application security model. Under the policy, a web browser permits scripts contained in a first web page to access data in a second web page, but only if both web pages have the same origin.
For example http://www.malicious.com or http://www.example.com can not access to storage in https://www.example.com
Additionaly the site should use SSL/TLS to encrypt the content and prevent the token from being stolen
If I am serving all of my web content over SSL, do I need to do another layer of encryption and sign my cookie data?
SSL/TLS only offers protection against communications being intercepted and/or modified. It guarantees nothing about text files sitting on a client's hard drive (i.e. cookies).
If you want to prevent a user from presenting your web application with falsified cookie information, then yes, you need to sign your cookie data. If you want to prevent a user from seeing the cookie data, then you should encrypt it as well.
Can localstorage value of a site be overwritten by xss(cross-site-scripting)? As far as I have verified in chrome and firefox, the localstorage value of a site is not accessible by a different site. Can anyone tell me whether the localstorage value can be read/write from a different domain in the browser by xss ?
Nowadays many websites, add third-party js libraries for Analytic, A/B testing, Marketing tools, Heat maps and ... You may be sure about your codes but if one of these scripts, is vulnerable then you should expect XSS attack easily and in this case, It can grab your localStorage. Don't use local storage for session identifiers or sensitive tokens. Stick with cookies and use the HTTPOnly and Secure flags. To prevent CSRF attacks on Cookies, almost all requests include one or both of: Origin Header and Referer Header. CSRF can be partially prevented by checking the HTTP Referer and Origin header from your API. CSRF attacks will have Referer and Origin headers that are unrelated to your application.
Javascript coming from reflected XSS or similar can do whatever normal JS can do on the domain where the XSS exists. So if example.com has stored things in localStorage and example.com also has an XSS flaw, then that XSS vuln can be used to extract or overwrite users data in localStorage. You could even use a reflected XSS, which exploits a DOM-based XSS using data from localStorage, meaning a client side persistent XSS.
Web storage (local and session) follow single origin policy. So it XSS access to web storage is not possible.