Today I learned that Django’s CSRF protection uses refer(r)er header checking in addition to checking a hidden form field against a cookie. It seems to be important, judging from docs and issue below.
It only checks this over HTTPS though. I’ve also noticed that almost no other website checks referer [since I turned off sending of said header and most forms still work].
So I have two questions:
- How would the attack work that would be possible without this check? Doesn’t https protect against man-in-the-middle attacks?
- How do other websites protect against it? And does Django not project for http?
The info that I found:
https://docs.djangoproject.com/en/1.8/ref/csrf/#how-it-works
In addition, for HTTPS requests, strict referer checking is done by CsrfViewMiddleware. This is necessary to address a Man-In-The-Middle attack that is possible under HTTPS when using a session independent nonce, due to the fact that HTTP ‘Set-Cookie’ headers are (unfortunately) accepted by clients that are talking to a site under HTTPS. (Referer checking is not done for HTTP requests because the presence of the Referer header is not reliable enough under HTTP.)
https://code.djangoproject.com/ticket/16870
Unfortunately, this check is absolutely necessary for the security of Django’s CSRF protection. Without it, we can’t prevent man-in-the-middle attacks on SSL sites. We made the decision that preventing MITM was a more valuable tradeoff than breaking sites for the small minority of users who block the header in a fashion which does not improve privacy.
Continue reading Why is referer checking needed for Django to prevent CSRF→