This may sound like a dumb question. I wanted to be clear about this. How does csrf token help to identify the cross site request if token is sent to the client first and the client sends back the same token? Wouldn't the malicious client get the response from the server.
If we check the origin while sending the token, then doesn't the token checking thing seem redundant?
How can we be sure that server will only serve the token to the authorized client and what is the best practice to transfer the token from server to client?
I had asked a related question here but needed more insight into it. So asking a different question here.
Hoping for some answer with example.
Thank you in advance
The client acquires a new CSRF token from the server by calling the REST endpoint baseURL/v1/csrf/tokens. The server generates a new, unique CSRF token and sends the token to the client in a custom HTTP response header. The header name is X-IBM-SPM-CSRF. The client retrieves the CSRF token from the custom header.
The client reads the payload from the cookie and passes it in the Authentication-Header to the server. The server validates the token based on the signature which is sent in the HttpOnly cookie. So, its CSRF-save and an attacker cannot steal the entire token via XSS because there is no JS-access to the signature.
Place the field containing the CSRF token as early as possible within the HTML file. Place the field that contains the token before any non-hidden fields and before any places where user-controllable data is embedded.
CSRF is basically about an attacker exploiting a user's existing session via the way cookies work in a browser. The underlying problem is that a cookie is sent with a request regardless of where (which origin, ie. domain) the request comes from, the only thing that counts is where it goes to. So if there is a user logged on to an application (having a session cookie), an attacker may try and get this user to visit his malicious website, from where the attacker can make requests to the application domain with the user's credentials (by fully POSTing the user to the application, or more subtly by creating ajax requests).
Note that this only applies if the authentication in the application is based on something that's sent automatically by the browser, most obviously a session cookie, but for example basic http authentication or client certificate authentication are also potentially vulnerable. Also CSRF only applies to requests that change something (state or data).
There is one important thing playing a role, the same origin policy (SOP) is browsers. A bit simplified, it means if something is downloaded from one domain (or more precisely: origin), then another domain will not have access.
So to protect against the attack described above and prevent an attacker on his own domain to have a user send unwanted requests to an application where the user is logged on, there may be several different strategies.
The application generates a csrf token, stores it in the user's session (server-side), and also sends it to the client by for example writing it in every form in a hidden field, or in one single field where Javascript can read it from and add to requests. This works, because an attacker on his domain cannot create a form or request with the valid token that's in the user's session, and also the attacker cannot read the token from an application page. Of course the attacker can try to download an application form to acquire a token, but then he would need credentials. The attacker needs both a valid user's session and the corresponding csrf token. The attacker may have his own appropriate account to log on, but then he could just perform the operation anyway. Or he may have a csrf token, but either unauthenticated, or to a lower privilege account. But he cannot have both, and that's the point.
So this protection basically validates that the request comes from a source that was actually rendered by the legitimate application and not somebody else.
Note that in this case, setting the token in a cookie is pointless, because the cookie will be sent automatically just like the session cookie.
A different strategy is to generate a token, and set it as a cookie for the client. The client then reads the token from the cookie, and sends the same token as a request header as well. The server only compares whether the request header and the cookie contain the same token. This works, because an attacker cannot read the application token from a cookie set by a different origin (see SOP above), but the application on the legitimate domain can. So the client sending the request effectively proved that it is running on the legitimate application domain. The benefit of this is that the application is stateless, does not need a session. The drawback is that it is slightly less secure.
(Interestingly, the token in this case can even be generated on the client, it still works, because the attacker on his own domain cannot set or read an application domain cookie, but it is definitely less secure as it is a crypto operation in the browser.)
As you correctly noted, another strategy could be to check the referer or origin of the request. It basically works, but is considered less secure. While double posting is considered secure enough for many applications, referer/origin checking is mostly not. There is a strong historical element to it I think, but still, it really is less secure.
There are many aspects of the problem, some that come to mind:
So for these reasons, simply checking referer/origin is not very robust, and another layer of protection should be in place.
A new invention by Google in Chrome is the SameSite
attribute to cookies (in addition to the already existing and widespread httpOnly
and secure
cookie attributes). As of now, it is only supported by Chrome and not other browsers.
As said above, the underlying problem is that cookies (ie. the session cookie) gets sent to the server based on the request target, and not the origin. This means that if attacker.com server a page to a user and that page sends a post request from the browser to legitapp.com, any cookie set by legitapp.com will be sent to legitapp.com. So if it is a user logged in to legitapp.com visiting attacker.com, the existing session can be exploited.
This is changed by the SameSite cookie attribute, which makes a cookie not be sent in such cases when the originating domain is different from the target one. It can be set to 'strict' or 'lax', which basically determines the GET request behaviour, but with any of those will prevent CSRF on non-GET requests.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With