Using JWT stored in HTTPonly & secure cookie: Vulnerable to CSRF. but not to XSS? - cookies

I understood webstorage is vulnerable to xss
And Cookie to CSRF also makes sense
What makes me puzzled is that it seems like implicitly said that cookie is not vulnerable to xss, but isn't it also vulnerable to xss?
If I can run a script on other's browser, I think I might be able to just send request to server & get important data cause browser automatically attach cookies & I dont' need to do anything to get authenticated.

If a cookie is set with the httpOnly flag, it cannot be accessed from Javascript (injected js cannot read or write such cookies), so it is not possible to steal the cookie value if it's httpOnly. This is very relevant for a session cookie. In this case, this cookie is not affected by XSS. Note that this is solely because of the httpOnly flag - cookies without httpOnly are affected by XSS, because they are accessible to Javascript.
Any cookie (regardless of flags*) will still be sent with any request to the server it was received from, but that is the realm of csrf, actually, it is the fundamental problem in csrf. If anybody (from any website) makes a request to a server, any cookie for that server will be sent, and the attacker can exploit csrf if there is no protection. That's why you need protection against csrf if you have cookie-based authentication.
Also note that if the page is vulnerable to XSS, than any csrf protection is useless, because xss can be used to read the token, wherever it is stored.
*Sidenote: the new SameSite cookie flag changes this, but that is only supported by Chrome.

Related

How does a xsrf token cookie protect against csrf?

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.

Does setting cookies 'SameSite=none; Secure' and providing CSRF-TOKEN suffice to prevent CSRF in embeddable web application?

My web application (myApp further) is embedded in iframe of a single third-party webpage. MyApp sets cookie Set-Cookie: JSESSIONID=38FE580EE7D8CACA581532DD37A19182; Path=/myapi; Secure; HttpOnly for maintaining users sessions. Sometime ago it stopped working in Chrome since https://blog.chromium.org/2020/02/samesite-cookie-changes-in-february.html update changed treating default behaviour for cookies without SameSite attribute from None to Lax.
I'm going to send cookies from myApp host with SameSite=None; Secure. Also X-CSRF-TOKEN header is included in every response. myApp javascript gets X-CSRF-TOKEN and puts it in header of every XHR request to myApp host. Does this suffice to prevent CSRF attack?
Should Access-Control-Allow-Origin: third-party-webpage header be added in responses?
I did more research and thought I would post my conclusion here.
I had misunderstood how the Antiforgery middleware worked.
The cookie configured by AddAntiforgery does not actually transmit the token to the client.
Instead it appears to be the encrypted or hashed token that is used to validate the token which must be provided in the header.
This allows the validation of the token to be done statelessly as the browser will pass the value of this cookie back with each request.
I refer to this cookie as the "validation cookie" below.
The middleware does not automatically transmit the token itself to the client.
That must be done by calling GetAndStoreTokens and providing the RequestToken value to the client to be set as a header for subsequent requests.
In our application we do that with a separate cookie (I call this the "token cookie" below).
Here's the Microsoft article demonstrating this technique.
I have determined that it is safe to use SameSite=None for the validation cookie and for the token cookie.
The SameSite setting does not have any effect on who can read the cookie value, it just determines whether or not the cookie will be sent to the server with future requests.
The validation cookie must be sent back to the server with future requests so that the token provided in the header can be validated.
It is acceptable that this cookie is sent even for cross origin requests since those requests will only validate if the token is provided in the header.
It is also acceptable for the token cookie to use SameSite=None since we are only using this cookie to provide the value to the client.
We never read this value from the cookie on the server when validating the token, the middleware reads the token from the header.
The value of the token cookie cannot be read by a different origin regardless of the SameSite property so that remains secure.
I also that realized that this exact pattern was employed by the Antiforgery middleware long before SameSite=Lax became the default value for cookies by chrome in 2020.
Prior to this the default behavior for the validation cookie would have always been None.
So I think it is reasonable to conclude that this technique is just as secure now with SameSite=None as it was before Lax became the default.
NOTE: There appear to be some browsers that don't handle SameSite=None correctly so the antiforgery process might fail for these browsers when the app is hosted in an iframe.

Security of storing Bearer token in cookies

My SPA uses React as front end and laravel API as backend.
When the user logs in (via axios and api), the api returns an access (Bearer token) as response. I use the react-cookie framework to store the access token as cookie in the Browser. This cookie will be read and used for any future request.
Is this the right way to do?
Isn't cookie data just something in the Browser that can be easily obtained by any attacker? Since it is just a file one the computer somewhere.
What is stopping an attacker from grabbing that cookie, impersonate as that user and start performing actions that requires authentication?
The token has a life span of lets say 1 year. It will only be refreshed every time the user logs in. I understand that if I set the life span shorter it will be more secure. However that will mean the user would have to log in constantly?
-----Update-----
Im not sure if any of the provided solution answered my question. A SPA app is front end based and the request can be from anywhere such as Postman, Mobile app, or any third party device that wish to talk to my backed server. So those device needs a way to store some access token locally to be used for any future request.
The only way I know this could happen is for my server to send some auth token to the requester and have it store it somewhere to be used for next request.
In this case, Im not sure if CSRF token or any other means would help my concern?
Just like facebook, if I clear my cache, I will have to re-login. That means facebook is storing something on my location computer so I can be automatically authenticated next time
I just want to add some disadvantages of storing tokens in cookies that you should also be aware of:
The max size of a cookie is only 4kb so that may be problematic if
you have many claims attached to the token.
Cookies can be vulnerable to cross-site request forgery (CSRF or
XSRF) attacks. Using a web app framework’s CSRF protection makes
cookies a secure option for storing a JWT. CSRF can also be partially
prevented by checking the HTTP Referer and Origin header. You can
also set the SameSite=strict cookie flag to prevent CSRF attacks.
Can be difficult to implement if the application requires
cross-domain access. Cookies have additional properties (Domain/Path)
that can be modified to allow you to specify where the cookie is
allowed to be sent.
------- Update -----
You can also use cookies to store the auth token, even it is better (at least in my opinion than using local storage, or some session middleware like Redis). And there are some different ways to control the lifetime of a cookie if we put aside the httpOnly and the secure flags:
Cookies can be destroyed after the browser is closed (session
cookies).
Implement a server-side check (typically done for you by
the web framework in use), and you could implement expiration or sliding window expiration.
Cookies can be persistent (not destroyed
after the browser is closed) with an expiration.
Your JS should not have access to the cookie. There are flags you can set on cookies that will help protect them and make sure they are only used for the correct purposes.
The HttpOnly flag is set on the cookie then JS will not be able to access it but it will still be sent with any request.
The SameSite flag will ensure that the cookie is only sent back to the site that gave it to you. Which prevents leakage.
The Secure flag will make it only send the cookie over a secured connection to prevent someone from sniffing it out of your web traffic.
Edit
You might want to lookup an authorization workflow but the gist of it is this:
User logs in with username and password
A JSON web token is issued upon login from the backend and sent to the browser
The JWT(JSON web token) can be stored in a cookie in the Web Storage(Session Storage) on the browser
Subsequent requests to the REST API will have the token embedded in the header or query string for authorization. With that form of authorization, your REST API understands who is making the request and what kind of resource to return based on the level of authorization
Please see #tpopov answer as he also made some really good points.

Action after XSS successfully

Let say my site is vulnerable by xss.
What happend then.
Javascript nowaday cannot get the cookie (HttpOnly is marked 'true')
Could the attacker do something specific on my site then?
Thanks.
You are saying that your website is vulnerable to XSS and it enabled HttpOnly flag.
If the victim's browser supports HttpOnly flag then the attacker can't get cookie of victim as it is not accessible by malicious script but what if the victim's browser does not support HttpOnly flag? In this case, the browser ignores the HttpOnly flag and creates normal accessible cookie, so the attacker can get cookie.
HttpOnly flag does not prevent execution of malicious script, so the attacker can do much more things.
Ex. Key logger, redirecting user to malicious sites, injecting fake login forms, etc.

JWT + cookies + HTTPS + CSRF

I already worked with JWT on mobile app but I will implement it on a website for the first time for the authentication and I have a little thing I still didn't understood :
if I use JWT token with localStorage, XSS attacks are possible
if I use JWT token with cookies, CRSF attacks are possible
..., but if I use JWT token over HTTPS with httpOnly+secure cookies and a token lifetime of 1 month, are CSRF attacks still possible in this case ?
I see all over the web for custom token with cookie or custom token with localStorage or JWT but I didn't explicitly get the answer of httpOnly+secure cookie + JWT + HTTPS + the need of CSRF.
If you are using JWT as an authentication token, it should be stored as a cookie marked httpOnly and secure, as apposed to using Local/Session Storage. As you mention, this protects against XSS attacks, where we are concerned about malicious JavaScript being injected into our page and stealing our session token.
A cookie marked httpOnly cannot be read by JavaScript, so it cannot be stolen in an XSS attack.
Local/Session Storage, however, can be read by JavaScript, so putting the session token there would make it vulnerable to an XSS attack.
However, making the session token cookie httpOnly and secure still leaves you vulnerable to CSRF attacks. To see why, remember that cookies are marked with the domain from which they originated, and the browser only sends cookies that match the domain to which the request is being sent (independent of the domain of the page the request was sent from). For example, suppose I'm signed into stackoverflow.com in one tab, and in another tab go to evil.com. If evil.com makes an ajax call to stackoverflow.com/delete-my-account, my stackoverflow authentication token cookie will be sent to the stackoverflow server. Unless that endpoint is protecting against CSRF, my account will be deleted.
There are techniques for preventing CSRF attacks. I would recommend reading this OWASP page on CSRF attacks and preventions.