In my spring based rest API, I'm using spring-session with HeaderHttpSessionStrategy. Given cookies are not used at all (session id is sent as a header), do I still need to worry about CSRF attacks?
I would say I'm safe, and I have read people agreeing that in this scenario CSRF protection is not needed, for example:
https://security.stackexchange.com/questions/62080/is-csrf-possible-if-i-dont-even-use-cookies
However, the Spring guys argue that whenever an application is accessed by a browser you do need CSRF protection: https://spring.io/blog/2015/01/12/the-login-page-angular-js-and-spring-security-part-ii.
In my oppinion, if you use the HeaderHttpSessionStrategy, CSRF attacks are not possible. If you save the header token as a cookie, it is actually the same approach as the XSRF protection works. So XSRF protection does not give you any additional protection.
I'd stick with the Spring guys. Generally they know what they are talking about. CSRF attacks consist of malicious code running while your request is in transit, pretending that the request comes from you.
Enabling CSRF doesn't do any harm other than adding an hidden field to your form and it protects your web application against such attacks. Why not use it then?
Related
I'm trying to secure endpoints on a website by protecting them with a nonce token.
I've been looking for out-of-the-box solutions to save time, but there doesn't seem to be any?
I've found out about anti-forgery tokens within asp.net, but these can be re-used and don't function like a nonce (use once, expires immediately after use).
Because of this, the anti-forgery token can't prevent replay attacks if the attacker has a cookie with the asp.net session identifier in it as wel (please correct me if I'm wrong).
Are there any easy to use guides or out-of-the-box solutions that allow me to use a nonce to protect my endpoints from replay attacks?
In Rails API applications we don't have out-of-box CSRF protection. In particular, storing access tokens (JWT for example) in the localStorage is not recommended, it is recommended to store in cookies (with httpOnly flag, SameSite, and etc.). But this time we're vulnerable to a potential CSRF attack. In a full-stack generated Rails app, a CSRF token is generated and embedded every time we open a form. But, I don't know and couldn't find anything how we protect against CSRF using tokens in Rails API apps. Do we have best practices or could anyone suggest an approach? I use access and refresh JWTs.
This is a usual tradeoff of API design, and you can choose from several different approaches, with different risk profiles.
You can store the access token in localStorage or sessionStorage, accessible to javascript, and accept the risk. The risk obviously is mostly around cross-site scripting (XSS), because this way javascript will have access to the token, and in case of XSS, it can be accessed by the attacker leading to session compromise. If talking about an API, responses should have the content type set to application/json, which makes the API itself protected from XSS in modern browsers. However, that does not mean the client (presumably a single page javascript app) is also protected, that can easily be vulnerable and leak the token. Some frameworks are better protected by default against XSS, some are not so much, and you might have checks like static scans in your SDLC that give you a level of assurance that might allow you to accept this risk. Also if your SPA needs to send the token to multiple origins (different api endpoints), you don't really have another option. In this case the token can be sent as a request header, and CSRF is not an issue.
Or you can exchange XSS for CSRF, by storing the token in a httpOnly cookie. This is generally considered more secure, because CSRF in general is a lower risk vulnerability (but still significant ofc). In that case you will not be able to send the token to different origins, but XSS will also not have access. This does not eliminate XSS for the whole application, but at least the token will be secure. The cost is now you will have to deal with CSRF. One way to do so is the samesite attribute to cookies. Using that for the token cookie will prevent most cases of CSRF, but it is a UX tradeoff, users of some browsers will not be protected, and some cases might be missed when using the lax option for samesite (like when a GET request changes state). Only having samesite as the protection will likely also be flagged in a penetration test for the reasons above.
If based on the above you decide to have more protection, you can implement something like double submit, and still keep it stateless, which these APIs many times aim to be. In case of double submit, you generate a random value, set it as a cookie (either directly on the client, or by a response from the server), and copy the same value from the cookie in a request header. The server only has to compare the value from the cookie to the one from the request, if they match, the request is ok. The reason this works is because an attacker on their own domain (origin) cannot set or read cookies for the victim application domain, this is ensured by the same origin policy of browsers.
A somewhat different approach might be applying a message authentication code (like HMAC) computed from the whole request and a shared secret (like the API key), and checking that on the server, but this is a can of worms, it's easy to have unprotected fields not covered by the HMAC, the server needs to have access to plaintext api keys so it can compute the hmac and so on - it's not at all straightforward to get this right).
Note that if the client app is vulnerable to XSS, that negates any CSRF protection as the attacker will have a way to get any secret from the client and with that, perform any request, with any computed field (like a valid token).
Looking at the docs for CSRF security and Spring Security there does not appear to be a way to mark a particular form/url as not needing CSRF protection. I have a site where in general I want CSRF enabled however there is one public page which has one form which is something something that people are very likely to bookmark and get errors due to a stale CSRF header between server reboots. Is there some way I can disable the CSRF protection on just one form/URL?
EDIT I am using spring-security-web version 3.2.7.RELEASE
I found it in thedocumentation
You can also specify a custom RequestMatcher to determine which
requests are protected by CSRF (i.e. perhaps you don't care if log out
is exploited).
This is my setup:
1 authentication server which gives out JWT token on successfull
authentication.
Multiple API resource servers which gives information (when the user
is authenticated).
Now I want to build my ASP.NET MVC frontend. Is it ok to take the token, which I receive after authentication, and put it in a cookie so I can access it with every secured call I need to make? I use the RestSharp DLL for doing my http calls. If it has a security flaw, then where should I store my token?
I would use this code for the cookie:
System.Web.HttpContext.Current.Response.Cookies.Add(new System.Web.HttpCookie("Token")
{
Value = token.access_token,
HttpOnly = true
});
You’re on the right path! The cookie should always have the HttpOnly flag, setting this flag will prevent the JavaScript environment (in the web browser) from accessing the cookie. This is the best way to prevent XSS attacks in the browser.
You should also use the Secure flag in production, to ensure that the cookie is only sent over HTTPS.
You also need to prevent CSRF attacks. This is typically done by setting a value in another cookie, which must be supplied on every request.
I work at Stormpath and we’ve written a lot of information about front-end security. These two posts may be useful for understanding all the facets:
Token Based Authentication for Single Page Apps (SPAs)
https://stormpath.com/blog/build-secure-user-interfaces-using-jwts/
Are you generating your own JWTs?
If yes, you should consider using a signing algorithm based on asymetric encryption, like "RS256" or "RS512" -- this way you can verify the claims in your client application without sharing the private secret.
Do you really need to pass the JWT into the Cookie?
It might be safer to just put a random id in your Cookie, which references the JWT access token, and do the de-referencing magic on the server which serves your web-app.
So I am trying to understand what to do here... I am doing a POST call to my Django server from iOS and I keep getting the 403 Error (Invalid CSRF Token). I am thinking about implementing a function that will return me the token (you will need to be logged in to access that function), and then add the token to my POST call.
Now... I don't understand what is the point of doing that? If I use TastyPie and the required login is APIKey... should I just exempt the csrf check?
To make sure I understand things right... is the CSRF generated per user session? Therefore, if I don't use Cookies, CSRF is not necessary?
How do people usually use their Django Servers with an iOS and making such POST calls?
Thanks!
You're right: if you don't use cookies to manage your sessions, you don't need CSRF protection. CSRF works because session cookies are automatically attached to the request; access tokens are not.
I personally found this article very useful. It is definitely worth reading, and would probably answer a lot of your questions.
As for tastypie: it allows SessionAuthentication. If you allow session authentication in tastypie, I suggest you look into a way to protect your users against CSRF. For other authentication schemes this doesn't seem necessary. As far as I know, Dmitry is right about tastypie disabling CSRF by default, which means it is strange that you get that 403 Error. Perhaps there is something else going on. Try wrapping the view in #csrf_exempt.
As for CSRF tokens, they are also called session independent nonces. They are meant to be permanent, but you probably know that is impossible for cookies. Anyway, this means that CSRF cookies persist through sessions.
You're right, CSRF does not make much sense in this case, because its purpose is to protect users from data tampering in a browser.
I believe that Tastypie disables CSRF on its views by default.