Storing "remember me" cookie and CSRF protection - security

I've been reading that "remember me" cookies are stored in "httpOnly" cookies, so they are not accessible by JavaScript/XSS. However, "httpOnly" cookies are vulnerable to CSRF attacks because they are sent with the request automatically.
To mitigate the CSRF attack, it is recommended to use the synchronized tokens pattern (have the server generate csrf tokens and crosscheck with the client) .
My question is, if a "remember me" cookie is available, is it possible for a CSRF attack (malicious JavaScript) to make a request and subsequently obtain the csrf token generated from the server? The concern is, if an attack has the cookie as well the token to send with requests, then the security of the app has been compromised.
If this is indeed possible, how could we prevent this?

No, the token cannot be read by another domain due to the Same Origin Policy.
If the request is made server-side to bypass the SOP, then the server isn't getting the token from the victim's browsing context therefore this cannot attack the logged in user (the server could only attack their own user that they used to get the token with).
Therefore, nothing to worry about (as long as you haven't enabled CORS of course).

Related

Session JWTs vs Session Cookies; Misunderstood?

For a React project, I'm trying to implement some auth solution. The following are what I'm considering.
Session Cookies are random tokens saved in HTTP only cookies sent by
the server. They are vulnerable against CSRF attacks. To protect
against, CSRF attacks, send a unique identifier with every HTTP
request. XSS protection is still required.
Session JWT are random signed tokens sent by the server. They are
vulnerable against XSS attacks. No CSRF protection is necessary.
Based off that, I decided to implement a Session JWT due to it being a random token, only need to focus on XSS protection, and session management abilities. In fact, I don't see the point of http only session cookies since an XSS attack can act via the user's browser. Preventing cookie access is barely counted as protection since an XSS attack can fool the user into providing credentials.
However, the more I research into this topic, the more confused I become. I keep getting conflicted info like JWTs being compared to Sessions instead of Cookies, no Session JWT implementations, and comments that state Session Cookies protect against XSS attacks.
Am I misunderstanding Session, Cookies, and/or JWT based off my prior descriptions?

Is https a pre-requisites for csrf token approach to prevent csrf attacks?

With the csrf token approach, when server sends form to the client, it also sends a csrf token. And when the client fills the form and posts it to the server, the server validates whether the token is same as what it had sent along with the form. This method prevents csrf attack because hacker cant guess the csrf token value when trying to generate a form post request.
Am I right to say that https is a pre-requisites for csrf token approach to prevent csrf attacks? Otherwise if it were a http request, the hacker can intercept the form, token and make changes and submit the form again.
I'd say no -as concept- , as one could say that a csrf attack would be possible over an https connection using an outdated TLS protocol for example, so ¿Would be TLS v1.3 required to prevent csrf attacks? Of course https will add another layer of protection over the connection but at a conceptual level I'd say that https is not 'required' for the CSRF token to work, but it's in a practical one.
OWASP itself says
"HTTPS by itself does nothing to defend against CSRF.
However, HTTPS should be considered a prerequisite for ANY preventative measures to be TRUSTWORTHY."

Is there any benefit for storing JWT in both a cookie and local storage?

I'm attempting write an authentication system for a node.js api using express. I've noticed that if I am going to use a JWT for authentication tokens, I have two options...
1.) Store the token in a cookie, and add CSRF protection.
2.) Have the client send the token in the Auth Header and add XSS protection.
My question is, is there any benefit to storing the auth token in a cookie, and having the client send it in the Auth Header for authentication? This way if for some reason the CSRF protection fell through, the request would fail if there was no authentication token in the header. Also, if XSS protection fell through, the request would still require the auth token in a cookie. I guess my thought is that this would provide more protection, and the only way it could fail is through a successful XSS attack followed by a successful CSRF attack.
Follow up question: Are CSRF tokens a full proof protection technique against CSRF attacks?
Firstly I recommend that you go through this answer first. I hope I've bern able to address your queries about CSRF and XSS here and why and how we should use cookie.
Secondly, your approach of using localstorage along with cookie is good. The only problem I see is localstorage cannot be used across sub domains. If you use cookie and set the cookie domain as example.com (replace example with your organization domain), it will be valid across all sub domains. Thus a user authenticated by your authorization server can seamlessly login to app1.example.com and app2.example.com. You won't be able to do this with localstorage.

JWT Refresh Token

A common scenario for user authentication follows these steps:
User registers and logs in using its credentials (username/password)
The server verifies the user's credentials and, if valid, returns an access token and a refresh token
The access token is sent on further requests and, if it is valid, the server responds with the requested resource
When the access token is no longer valid, the server requests the client to provide a refresh token in order to issue a new access token
The server receives the refresh token and two things may happen:
if the refresh token is valid, a new access token is issued to the client
if not, the server requests the user to authenticate
For the client to be able to send the access token in every request, the token should be stored either on browser storage (local/session storage) or cookies, which makes it vulnerable to XSS (Cross-Site Scripting) attacks. This problem may be mitigated if we set a short lifetime to the access token.
My question, however, is regarding to the refresh token. This token should have a long lifetime and since we use it to get new access tokens, it would be a problem if an attacker would intercept it. So storing this token on the client side might not be a good idea, right?
But, what are the alternatives?
Can we store it in a cookie set with the "httpOnly" flag? But wouldn't this make it vulnerable to CSRF (Cross-Site Request Forgery) attacks?
Is it safe to encrypt the token and still save it on browser storage?
Thank you in advance. Best regards!
which makes it vulnerable to XSS (Cross-Site Scripting) attacks.
To clarify, the cookie is only vulnerable to a XSS attack should there be a vulnerability on your site that makes this possible.
Can we store it in a cookie set with the "httpOnly" flag? But wouldn't
this make it vulnerable to CSRF (Cross-Site Request Forgery) attacks?
Although the httpOnly flag cannot be used in some forms of CSRF protection due to the need for it to be accessed client-side, flagging a cookie as httpOnly does not increase the risk to your system in any way - httpOnly is more restrictive.
Is it safe to encrypt the token and still save it on browser storage?
Not really because anyone or anything that can access browser storage can access the cookie value and present it. It doesn't matter what form it takes - encrypted or not - if it can be used directly without an external key. Don't worry about this too much - put trust in the browser to keep this secure, however ensure the rest of your site is as secure as possible.
You are right that the refresh token is viewed as more sensitive than the access token. You can store this in a cookie, however make sure that it is set to httpOnly and has the secure flag set too to ensure it is only transmitted over encrypted HTTPS connections.

Refreshing CSRF Tokens

I am trying to implement a user friendly anti CSRF mechanism.
Currently my application program sets a cookie and session variable with the anti-csrf token and sends it to user.
Whenever the user makes an unsafe request(POST,DELETE,PUT) javascript reads the cookie and adds the token to the form which is sent via an ajax request
On server the form value is compared with session contained value.
Problem is my application will be open in multiple tabs and it it highly probable the the token will expire on server.
Is it a good practice to get new csrf tokens from a server file like
get-csrf-token.php
Because anyways the attacker cannot read the response from cross site requests(considering jsonp and cors is disabled)
EDIT:
I plan to keep single CSRF token valid per hour per session and the web applications will re-request new tokens after an hour
Is there anything wrong with this approach?
You only need one CSRF token per user session. As any attacker cannot read the token due to the Same Origin Policy, you do not need to refresh the token until the next session is active. This will mean there will be no problems with your application being open in multiple tabs.
Your approach is an implementation of the Synchronizer Token Pattern CSRF protection mechanism, which is the OWASP recommended approach. As JavaScript is used to add the value to the request, you can't mark your cookie as httpOnly. This would have prevented any XSS vulnerabilities from allowing an attacker to grab your cookie value. However, if you do have any XSS vulnerabilities, these are slightly more serious than CSRF ones and should be addressed immediately anyway as there are other attack vectors once an XSS flaw is found.
See this post for some pros and cons of some CSRF mechanisms: Why is it common to put CSRF prevention tokens in cookies?
In my project, I use cookies for managing authentication of users, and use session for generating the CSRF token.
When generating the form, it should be included in hidden field. For ex:
<form method="post" action="/paymoney">
<input type="hidden" name="csrf" value="csrf value" />
...
</form>
When user makes an request, the server should authenticate the request first (via cookie). After that, the server get the correct user session and verify the CSRF token.
Note that, you should care about the time out of CSRF token. The more expired time of this token, the less efficiency you can get. But if the expired time is too short, it cause a trouble that some ajax call can not work although the authentication of user is still valid.

Resources