Closed chr15m closed 9 months ago
Not sure what you mean, either the header or form body is the recommended approach to send the token from the frontend to the backend. But you still need a way to send the token to the frontend.
As for the Django implementation, you'll see it says this:
Acquiring the token if CSRF_USE_SESSIONS and CSRF_COOKIE_HTTPONLY are false The recommended source for the token is the csrftoken cookie, which will be set if you’ve enabled CSRF protection for your views as outlined above.
For some reason they're recommending you to use a cookie when these two things are false. It's strange, because it should mostly be recommended to do this in a case where CSRF_USE_SESSIONS
is true and CSRF_COOKIE_HTTPONLY
is false, not when both are false. It's a little negligible if you have secure flag set. The idea is the Synchronised Token Pattern stores a generated token in the backend against the users session, then the value sent from the frontend is compared to the value in the backend. As the value is stored in the backend, there's no way to fake a value, it has to match.
Then they say this:
Acquiring the token if CSRF_USE_SESSIONS or CSRF_COOKIE_HTTPONLY is True If you activate CSRF_USE_SESSIONS or CSRF_COOKIE_HTTPONLY, you must include the CSRF token in your HTML and read the token from the DOM with JavaScript:
In this case, the main cookies is http only, but you could still send a copy of it by cookie if you wanted to. The point of the Double Submit Pattern is that the frontend sends two values. It sends a cookie, which should be httponly, then it sends an additional value either in a header or form body, the backend then compares both of those values in some way. The additional value could also be sent to the frontend in a regular cookie in this case
In addition, their documentation for CSRF_USE_SESSIONS says this:
Storing the CSRF token in a cookie (Django’s default) is safe, but storing it in the session is common practice in other web frameworks and therefore sometimes demanded by security auditors.
Django allows you to use a different pattern based on the configuration, to me it does appear that they have this backwards, but Django also has many other layers of middleware and security that a typical Node backend isn't going to have (unless the person configures and sets them all up themselves), so it's a completely different context.
Generally speaking, it can be fine to send the token by cookie, however see the discussion here regarding one incident where a subdomain was used to target the main domain, and had the cookie been httpOnly and used differently, this attack would not have been successful.
Django is a well-established framework, and I've worked with it professionally too, I would need to look deeper into the exact implementation of their CSRF protection to comment better on it, but based on their documentation alone, it does look like you could technically configure it and use it in a way that isn't secure. I try to avoid that possibility with csrf-csrf and csrf-sync, hence these implementations are provided separately, rather than together where the one you use depends on config.
Edit: Based on the Django implementation here, they compare the token from the request cookie with the value delivered by the frontend (via body or header), and in this case, OWASP does recommend that this cookie is http only. So by default, this isn't best practice, but it's up to the dev to ensure the configuration is appropriate for their needs and use case. Refer to the _get_secret
and _check_token
functions in the linked Django code.
As of course, if you have an XSS vuln, CSRF protection won't help you. But in the case of the subdomain example on twitter, there can still be cases that slip through and can be mitigated by ensuring you have the best practice settings.
Not following best practices doesn't necessarily mean insecure, it just means there's things that you potentially could be doing, which may or may not make a difference for your use case. I would not recommend Django's default configuration for anything other than a development environment, I would highly recommend using session based CSRF and ensuring secure and http only flags are true.
Django gives you the power to configure a content security policy and appropriate CORS settings out of the box. With Node, having these additional securities is optional and their utilisation is entirely up to the dev.
Hi, I'm reviewing csurf replacements (for Sitefox) and I came across your libraries. Thank you very much for taking the time to build these and put them into public for general use. :pray:
In your documentation on both modules it says:
And later;
I am curious why this is? I notice that the current version of Django still advocates this approach:
https://docs.djangoproject.com/en/4.2/howto/csrf/#using-csrf-protection-with-ajax
Are they not following security best practices? Thank you for your time!