Best Practive for XSRF/CSRF Secured REST Calls? - javascript

I want to secure my REST calls against XSRF attacks. What I am doing is the following:
The server sends a logged cookie to the browser after the user has loggedIn successfully.
On each request (GET, POST, DELETE) I send the loggedIn cookie to the server as well as an XSRF token (XSRF token is sent as header parameter) which is generated by hashing the JSESSIONID cookie with MD5 like it is proposed here. (JSESSIONID is not sent to the server)
The server verifies the XSRF token my hashing the JSESSIONID cookie with MD5 and compares the result with the XSRF token from the request.
If both values are equal the server processes the request.
Edit: I did not use the standard approach because I use GWTP REST instead of GWT-RPC.
Question:
Is this a good approach? Does it matter if I send the LoggedIn Cookie to the server? Does it increase the vulnerability?

Q. Is this a good approach?
The dev guide states:
This stateless XSRF protection implementation relies on the fact that attacker doesn't have access to the session cookie and thus is unable to generate valid XSRF token.
The XSRF token is a simple hash of the JSESSIONID cookie and MD5 is not recommended for password storage any longer (old version of page, current version is here):
As such general hashing algorithms (eg, MD5, SHA-1/256/512) are not recommended for password storage.
However, as an attacker has no method of retrieving the JSESSIONID value, this method is simply another way of executing the OWASP recommended double submit cookies XSRF prevention method and is secure. To answer this question it seems like a good approach to me.
Q. Does it matter if I send the LoggedIn Cookie to the server?
Yes you should send the authentication cookie too so that your API can authorise the user in the normal way too.
Q. Does it increase the vulnerability?
There is no extra risk in sending the cookie with the request as well. It would be a good idea to protect your REST service with HTTPS so all data is encrypted whilst in transit.

Related

Where to store the access token so it cannot be vulnerable to XSS

I am developing a web app and I am on a process of handling the Authentication of user. I am able to get the access token by initially making HTTP POST call to the API.
The idea know is where to store it so that it is not vulnerable to XSS.
Have heard of HttpOnly Cookie which makes it possible that the cookie is readable by the client (javascript), but the thing is why would I need something to store on my end when I cannot access it. How do I sent back to the backend (API) access token stored into coockie with http only since I cant get it so I am unable to attach it into headers of my http request.
Also, can I add a coockie with flag HttpOnly using javascript?
HttpOnly means you cannot read it from Javascript on the client but the browser is still aware of that cookie and it is being added to any subsequent request you are making to the server.
It can be useful for an auth session cookie for example.
Session cookies are usually opaque tokens that are meaningless to the user and are meaningful only to the server. Thus there's no real reason why the client code would need to read them
Also, can I add a cookie with flag HttpOnly using javascript?
No

CSRF protection in singlepage web application

My Application structure as follows
1)API server running in api.mydomain.com
2)Frontend VUejs application running in www.mydomain.com
So i implemented authentication via httponly cookie.
But little confused with CSRF token implementation
Mysolution
1).CSRF token from the url like /getCSRF.
2) Store it in localstorage.
3) Send with every request.
But i don't think its the good way does anyone have suggestion?
First things first: Feel free to use session-based authentication in combination with the httpOnly (prevents your session cookie to be hijacked via XSS attack) cookie. Nothing wrong with that.
After a certain action (e.g. login), generate a CSRF token and store it in a cookie (make it accessible to JavaScript). You can HMAC the token with server secret so that attacker cannot recreate a CSRF.
Sure that CSRF will be sent as a cookie in each request, but the trick is to send it and expect it in a custom header (e.g. X-CSRF-HEADER). The final step is to check its validity.
The key idea is that attacker cannot attach custom headers while performing a CSRF attack.

JWT Token and CSRF

I am still not clear in regards to the JWT and CSRF working together. I understand the fundamentals for the JWT (what it is and how it works). And I also understand the CSRF when used with sessions. Similarly I understand that there are risks involved with storing the JWT in localStorage and that's why you need the csrf token. So my question is, how do I use them both. For simplicity say that I have a login page.
1) I have the user signing in and once the email and password are consumed if the user is authenticated the server will send a CSRF and will store a httpOnly cookie with the JWT (how do I set the cookie using PHP). What I understood is that you can use header('Set-Cookie: X-Auth-Token=token_value; Secure; HttpOnly;');please confirm if thats the way to do it.
2) Once I have set the cookie with the JWT. How I am sending the CSRF token with subsequent requests> From what I understood, you set them in the headers. So if I am making an Ajax request I will put them in the headers.
3) Once the request is made and the CSRF token is sent along with the request. How is the validation made. What am I comparing?
Last, is this safe to implement!
I would highly appreciate if you could include as much details as possible.
One approach that I've seen and used myself is to include the CSRF token inside the JWT as a claim. So when the user sends username and password, you can do the following:
If username and password are correct, proceed with the following listing.
Create a new JWT and include a generated CSRF token in the payload as a claim, then sign the JWT.
Respond to client's authentication request by setting an HTTPOnly cookie which contains the JWT. This ensures that only the browser (not the client side app and possibly malicious scripts) has access to the JWT. It's also a good idea to set the cookie to secure. This prevents the browser from sending the cookie if an unsecured communication channel is used (i.e. not https).
When setting the JWT cookie, you should also set an HTTP header which will also contain your generated CSRF token. Note that now you will have the CSRF token in two places—inside the JWT cookie and in an HTTP header.
In your client app, store the CSRF token from the header into localstorage.
For each request, take the CSRF token from localstorage and include it as a request header (the cookie containing the JWT is passed along automatically by the browser).
The server should read the JWT from the cookie, validate its signature and read the CSRF token from the JWT's payload. Then it should compare it against the CSRF token that's in the request header. If they match, the server can continue processing the request.
I suggest you to watch this talk about JWTs. It goes into more details about the same approach (also with nice diagrams). Feel free to watch the entire talk or if you're interested specifically in CSRF, start from 36:29.
The following is a slide (from the presentation linked above) that demonstrates how JWT and CSRF tokens could be used together. I annotated it with red numbers which correspond to the listing above.
The common paradigm to defend against CSRF it to generate a token for each "form", and validate that the token that was set for the specific form is correct.
That way, attacker can't guess the token therefore can't make an external form that sends to your server.
Usually, the method to set that token is via Cookie and the client app will attach it to some custom header, that will give you an additional protection, then, the server should compare between the cookie value and the header value.
It is important that the token will be valid only for one session, otherwise, an attacker can reuse the same token that he got in the attack vector.
JWT, is a method to authenticate the user to the system not to validate that the request was valid.
I will try to explain by example, assume you are didn't implemented any protection against CSRF, but you do have a mechanism to authenticate your users (with usage of JWT), so the user logged in with the correct user & pass, your server will send a JWT, the client will save it to localStorage / memory.
Now, the attacker can craft a form on his site that will point to your server, assume that he knows the users JWT token (he got it with other methods like MITM), all he needs to do is to trick the user into going his page with the form, and the form will be sent to you with any problem, your server will accept the request and the attack will succeed.
If you implement any CSRF mechanism, the attacker at the example will not be able to guess the current token, therefore your server will ignore his request.

Why should I put a CSRF token in a JWT token?

I want to bring a doubt about JWT tokens and CSRF from the Stormpath post that explain the advantages and disadvantages of storing the JWT either in localStorage or cookies.
[...] if you are reading values out of a cookie using JS, that means you
can't set the Httponly flag on the cookie, so now any JS on your site
can read it, thus making it the exact same security-level as storing
something in localStorage.
I'm trying to understand why they recommend adding the xsrfToken to
the JWT. Doesn't storing your JWT in the cookie and then extracting it
out and placing the JWT in the HTTP header and authenticating the
request based on the HTTP header accomplish the same thing as
Angular's X-XSRF-TOKEN? No other domain could make requests on a
user's behalf if you authenticate based on the JWT in the header,
since other domains cannot extract the JWT from the cookie. I don't
understand the purpose of the xsrfToken in the JWT - perhaps its just
an additional layer of defense - meaning that attackers would have to
have a compromised script on your site and CSRF a user at the time. So
they'd have to hit you in both ways to be able to pull of an attack.
The post is linked in this answer where says:
The last thing is to ensure that you have CSRF protection on every
HTTP request to ensure that external domains initiating requests to
your site cannot function.
[...] Then, on every request into your server, ensure that your own
JavaScript code reads the cookie value and sets this in a custom
header, e.g. X-CSRF-Token and verify that value on every request in
the server. External domain clients cannot set custom headers for
requests to your domain unless the external client gets authorization
via an HTTP Options request, so any attempt at a CSRF attack (e.g. in
an IFrame, whatever) will fail for them.
Even if they could set custom headers, they couldn't access the cookie where the JWT token is stored because only JavaScript that runs on the same domain can read the cookie.
The only way they could is via XSS, but having an xsrfToken in the JWT is compromised too if exists XSS vulnerabilities because a malicious script running in the trusted client domain could access the JWT in the cookie and include a header in the request with the xsrfToken.
So the equation should be:
TLS + JWT stored in secure cookie + JWT in request header + No XSS vulnerabilities.
If the client and server are running in different domains, the server should send the JWT and the client should create the cookie with the JWT.
I think that the equation is still valid for this situation.
UPDATE: MvdD agree with me:
As the browser does not automatically add the header to your request,
it is not vulnerable to a CSRF attack
I am the author of the Stormpath Blog Post. Storing XSRF token in the JWT isn't about that it is in the JWT, it is about that it is in a cookie. The cookie should be httpOnly, so you can not read it from Javascript.
Now, I think the point that caused a little confusion is where I talk about angular. Angular sets it's only XSRF cookie as well (which is not httpOnly) to put it into the header at request time (which can only be done by javascript on same domain). These are not the same cookie.
If you think about implementing XSRF support in your application, this has been done with storing server side state and the point of storing the XSRF. Storing it in the httpOnly cookie is about being stateless with XSRF. Here, you would validate the JWT signature, get the XSRF out of the claims, and compare it to the header.
The answer to your question is so that you do not need to store state on your server.
My understanding was this:
Store JWT is an HTTPonly cookie.
In that JWT, store a hashed version of an XSRF token.
Send the client the XSRF token when they sign in so they can store it in local storage
Later when the client sends requests, the JWT is automatically sent with each request via cookies and then you also send the XSRF token via a header or query variable and on the server side, re-hash to compare to what's in the JWT on the server
Your JWT is protected from being stolen in a XSS and you're protected from XSRF. XSS could still execute on your browser but could only do damage for that session in the browser. Ultimately, You couldn't stop someone from writing a really detailed script that just ran on your browser, so conventional safeties to protect from XSS are still needed by the web developer.

What is the challenge/response method to securely authenticate with a Server without HTTPS (without sending out password)?

What is the challenge/response method to securely authenticate with a Server without HTTPS (without sending out password)?
I have an app (Javascript client) that connects over CORS (authenticate) to our backend which in turns will return a token containing the claim (JWT) over non-HTTPS. The REST is stateless so we do token-based and not have session at all.
When the client gets that token, (containing claim) it is added to the header for each request of the client and therefore the backend knows which User Id is doing that request and do the appropriate thing. So far this works for us. My concern is with the authentication process and with the security of each request.
To authenticate the clients sends out email and hashed password pair, however I want to know if there's a more secure way even without using HTTPS for now. I've read to not send the password but do a challenge/response, but what is the implementation of that idea?
And last question would be, even if we get around with the authentication process securely, how about on each request which contains the token with claim can it be secured also?
There is no possible way to do this securely without HTTPS. For your server to authenticate users, you need some kind of token (cookie, adding to requests like you have, etc.) However, the problem is that, without https, an eavesdropper can add javascript to your page. They can then capture the token and use it themself (stealing all the user's data), or modify it. If you want your product to be in any way secure, you need HTTPS.
Edit: I guess you could store some information about the device sending the request (user agent and such), and only allow the token to be used on that device. However, an attacker could just fake the user agent when they reuse the token, so this wouldn't be too hard to bypass.
Challenge response is a mechanism to send passwords in non-clear way.
1°/ client and server must share a cyphering key : best is to manually add certificate on client but could be a little bit heavy. Another solution is to store the key only one time into localStorage.
2°/ client requests a challenge to server : this is a "phrase" generated by server
3°/ client concats its password with this "passphrase", ciphers and send response to server : Challenge => Response
4°/ server decrypt message, search and remove its passphrase to get password.

Categories