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.

Reply via email to