Django sets a CSRF protection token on the user's machine via a cookie. It then asks for the token on POST requests. If these two don't match, it returns a 403.

If I change manually both the cookie and the token value I send in the request, the request is accepted. Django does not verify that the token value was set by the server. As long as cookie and request match, it won't return a 403.

This doesn't seem safe. What if another website spoofs my domain and set a new cookie and then sends the CSRF token value of the new cookie in the request? Django will compare the two and consider the request legit.
Are they any packages that implement this differently or am I missing something?

  • That's quite a cool finding! Why don't you validate your proposed exploit and file a bug report? Commented Dec 17, 2013 at 19:54
  • I'm not sure it's something new. It looks like they're implementing a Session-Independant Nonce (cf page 5 seclab.stanford.edu/websec/csrf/csrf.pdf) in which case that is a known security flaw of this implementation.
    – Youcha
    Commented Dec 17, 2013 at 20:09

2 Answers 2


Django is using a Double-Submit Cookie and it is accepted as a safe method of CSRF prevention. Why? Because, It is impossible for an attacker to control the cookie filed in a CSRF attack. A CSRF attack is relying on the fact the browser manages cookies, and will include cookies associated with a target domain to the forged HTTP request. It is possible to read and modify the non-HTTPOnly cookies using XSS, however, almost all Anti-CSRF measures can be undermined by XSS.

To answer your question:
Yes, Django's CSRF protection system will prevent a CSRF attack from succeeding, so as long as the application isn't vulnerable to XSS.

  • What about crlf injection, what if there is response splitting vulnerability in the response header and we could set another cookie named csrftoken and give it a test value ?
    – StackB00m
    Commented Dec 13, 2016 at 10:53
  • @StackB00m yes, CRLF injection could be used in this way. Also CRLF injection can be used to control the body, bypass the XSS auditor and ride on the browser's authed session. Its rock paper scissors: crlf inj > xss > csrf - but the CRLF and XSS would be unexploitable if it has a CSRF token!
    – rook
    Commented Dec 15, 2016 at 17:45
  • I dint get this - " CRLF and XSS would be unexploitable if it has a CSRF token! "
    – StackB00m
    Commented Dec 15, 2016 at 19:50
  • @StackB00m HTTP Response splitting (CRLF injection in HTTP) and Reflective-XSS are both useless if you can't trigger them from a malicious page. If a CSRF token in place, then a malicious site is unable to send a cross-site request needed to carry out the injection. XSS can always be used to read the CSRF token, just so long as you can get code running on the target origin... Rock, Paper, Scissors.
    – rook
    Commented Dec 15, 2016 at 20:45

Django's CSRF protection is not broken per se; it is generally considered sufficient for many applications.

But indeed the 'double-submitted cookie' model means that CSRF protection will fail in the case an attacker can plant a cookie on a user's browser: the attacker could set the cookie and then immediately submit a form with the same value in its token field. This means there is a potential escalation route from cookie forcing to CSRF, and this can be unacceptable for more security-critical applications.

Cookie forcing is not generally a simple attack in itself. The same-origin policy should normally prevent an attacker site from setting a cookie on another site. If the target site has an XSS flaw then obviously you can set/get cookies, but then if you have XSS you have already lost so badly there is no point worrying about CSRF.

Where this can fall down is hosting factors that may be out of your control as an application author:

  1. When your site is on HTTPS and the attacker has man-in-the-middle against a user. Although they cannot spoof your HTTPS website, they can direct the user to an HTTP address on the same hostname, and from there write a cookie that will be sent by the browser to your HTTPS site later. (This can be somewhat mitigated using the Strict-Transport-Security header.)

  2. If your site is on a.example.com and there is another application running on b.example.com that is vulnerable to XSS, that application could be abused to set a cookie on all of example.com, which would then be sent by the browser to your app at a.example.com.

It is a design weakness of cookies that an application cannot tell whether the cookies were originally set with matching domain and secure properties, and that if two same-name cookies are set with differing domain/secure the results are essentially undefined.

The 'synchroniser token' and 'encrypted token' (HMAC) approaches include a server-side secret unknown to the attacker that prevents the escalation from cookie forcing to CSRF.

Unfortunately Django doesn't lend itself to clean substitution of shared functionality. To improve or replace the CSRF mechanism without breaking all the apps that rely on it involves a bunch of ugly monkey patches.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .