Hi Steve, First let's get into how cross-site request forgery works: when you are logged in to bank.com, your browser saves a session cookie and sends it with every request. Now when you visit evil.com, they may include a piece of javascript in their side that sends a POST request to bank.com/transfer/ to transfer $1000 from your account into theirs. Your browser executes the javascript, and happily sends a request to bank.com/transfer/ along with the transfer details and your session cookie. The session cookie authenticates the request as coming from you, so the bank has no reason to suspect that you didn't want to transfer the money. The issue here is that your browser sends the session cookie with *every *request.
Django uses a so-called double submit cookie[1] to protect against CSRF attacks. This is a well-documented pattern for CSRF protection. In addition to the session cookie, a CSRF token cookie is set in the browser. This contains a randomly generated value that is unique to your browser. This value is also included as a form field (or a request header) in any POST request you make. When you send a request, Django checks if the two values are the same. If they are, then that proves (up to a point) that the request is from a party that has legitimate access to the token value. Barring any more extensive attacks (such as cross-site scripting), evil.com has no way to get the correct value of the CSRF token. Javascript executed on evil.com has no access to the cookies for bank.com, and opening a page from bank.com in e.g. an iframe also disallows access to the content of that iframe. Only a legitimate party (i.e. you filling in a form on bank.com) has access to the correct token and can submit the same secret as the one in the CSRF token cookie. As for the "cipher algorithm", this is actually just a padding algorithm to make the value randomized on each page load, while keeping the secret the same. You are right that anyone can reverse this, but that is not an issue. Randomizing the value prevents a class of attacks that includes BEAST, CRIME and BREACH attacks. These attacks work by injecting a value into the page in close proximity to the CSRF token (i.e. when a page displays a GET parameter) and seeing what effect it has on the compression of that page. If the compressed page becomes shorter, then the injected value likely has some values in common with the CSRF token. This allows for recovery of the secret token byte-by-byte, so that evil.com can bypass the CSRF protection in place. Randomizing the value, even if the original value is easily recovered, prevents this class of attacks entirely. I hope this gives you a better understanding of how CSRF protection works in Django. If you have any more questions feel free to ask here or on IRC (nick: knbk). Marten [1] https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet#Double_Submit_Cookie On Monday, January 15, 2018 at 11:03:22 PM UTC+1, Stephan Doliov wrote: > > Just curious, I recently went on a source code studying binge and took a > look at the CSRF middleware that comes with Django. I appreciate the work > and effort of the authors, but I am not sure I gain anything by deploying > it to my site. Here is why: > The middleware token assigned to a form and to a csrftoken cookie are > ciphertexts of the same underlying key (by default, the underlying key is > chosen as 32 randomly chosen (with replacement) chars from a set of 62 > chars. So the easy workaround can be done in one of two ways > > 1) Write a script that just harvests the middleware token from a form > "protected" with such token and use the value of that as the csrftoken > cookie. > As the middlewaretoken is a cipher of the underlying token, obviously > using the the same string as the value to the csrftoken cookie will satisfy > the middleware's demand for authorization of the resource (e.g. POSTing to > the form) > > 2) Learn the easy cipher algorithm the csrf middleware uses and present a > csrf token cookie that will decode to the right value. > > In either case, I am not convinced that meaningful protection against CSRF > types of requests are provided by the middleware. Am I missing something? > > Wouldn't it be more secure to just have middleware that whitelists as a > series of origins (aka CORS) and then, unlike CORS, actually perform > reverse lookups on the dns of the whitelisted domains? (Of course, this > assumes that the hosts that might want to make cross-site requests ahve > access to managing their reverse DNS). > > Am I missing something; or, if serving performance is a top goal of mine, > should I just ditch the csrf middleware? (and maybe rate limit client > requests to prevent DoS attacks)? > > Thanks, > Steve > -- You received this message because you are subscribed to the Google Groups "Django users" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscr...@googlegroups.com. To post to this group, send email to django-users@googlegroups.com. Visit this group at https://groups.google.com/group/django-users. To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/91025dd6-a7bf-4927-861b-67463d3ef523%40googlegroups.com. For more options, visit https://groups.google.com/d/optout.