Hi David, Our CSRF protection is a bit different from that implemented by many other frameworks. The recommendations we (wearing my OWASP hat) make as OWASP tend to be conservative and lean towards "safe is better than sorry." Security and pentest companies tend to make similar recommendations because they don't have the resources to make absolutely certain that everything is implemented correctly.
In many frameworks, sessions and CSRF are inextricably linked. You can't have a form without starting a session. Because Django gets used in so many different ways, we provide an implementation that allows you to have CSRF protection without sessions (and without storing any data persistently server-side). This is useful, for example, if you have a cluster of machines processing requests behind a load balancer- you don't have to have keep server-side data in sync across the cluster. The way our CSRF tokens work is pretty simple. Each form contains a CSRF token, which matches the CSRF cookie. Before we process the protected form, we make sure that the submitted token matches the cookie. This is a server-side check, but it's not validating against a stored server-side value. Since a remote attacker should not be able to read or set arbitrary cookies on your domain, this protects you. Since we're just matching the cookie with the posted token, the data is not sensitive (in fact it's completely arbitrary - a cookie of "zzzz" works just fine), and so the rotation/expiration recommendations don't make any difference. If an attacker can read or set arbitrary cookies on your domain, all forms of cookie-based CSRF protection are broken, full stop. Generating a new token for each request is problematic from a UI perspective because it invalidates all previous forms. Most users would be very unhappy to find that opening a new tab on your site invalidated the form they'd just spent time filling out in the other tab, or that a form they accessed via the back button could not be filled out. That said, there are a few conditions that need to be met in order to have Django's CSRF protection work to the fullest extent: 1) Use HTTPS. Use it on your entire site. Use it all the time. Redirect to the encrypted version for all unencrypted requests. If you don't do this, no CSRF protection in the world can protect you from a man-in-the-middle. 2) Use HSTS. Set it for several months. Use "includeSubDomains". This means that no matter what your users type, and no matter what the man-in-the-middle does, your users will always access your site securely if they've been there at least once before. 3) Validate the HOST header in your httpd. Don't allow arbitrary requests to fall through to Django. Serve your site only for the appropriate domain. See the most recent security advisory for more information about this. If you do these 3 things, you'll be able to take advantage of the other feature that makes the CSRF protection stronger - strict referer checking (only enforced over HTTPS). This means that even if a subdomain can set or modify cookies on your domain, they can't force a visitor to post to your application, since that request won't come from your own exact domain. You should make every effort to avoid allowing subdomains to set or modify arbitrary cookies, but Django's CSRF protection prevents an attacking subdomain from causing your users to submit authenticated posts. Please feel free to come find me on IRC if you want to chat more about this - I'm PaulM there and I'm usually in #django-dev. You can also email me directly if you want to talk in private about your specific deployment. So, the tl;dr version: Use HTTPS and HSTS. The recommendations you received are generally good, but aren't relevant to Django's CSRF protection. -Paul -------- As always, if you think you have found a security issue with Django, please email secur...@djangoproject.com, rather than posting to the public lists or the bug tracker. -------- -- You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com. To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.