I agree with Jacob on both points.

+1 from me, especially since neither of these changes should require
changes in application code which is already using the interface
correctly.

-Paul

On Tue, Jul 30, 2013 at 1:22 PM, Jacob Kaplan-Moss <[email protected]> wrote:
> Hey Shai -
>
> I have no objections to this change. I think it's got a slight whiff of
> security theatre, in that it *looks* like it adds more protection than it
> *actually* does. However, I, too, have spent a ton of time talking auditors
> down from "OMG Django is vulnerable to CSRF!" and I'd like to do less of
> that. I like that rotating SECRET_KEY invalidates CSRF tokens.
>
> Time-limiting is a nice feature too, actually. Again the perceived security
> is higher than the actual added security, but the general principle of
> giving people more control is a good one. I'm sure there's some audit
> checklist out there that has "CSRF tokens must not be valid for longer than
> X hours" or something on it, and helping our users tick those boxes isn't
> such a bad thing.
>
> So yeah, lukewarm praise from me at best, but since there's at least a bit
> of real improvement here I see no reason this shouldn't go in. +1 from me.
>
> Jacob
>
>
> On Sat, Jul 27, 2013 at 6:12 PM, Shai Berger <[email protected]> wrote:
>>
>> Hi everybody,
>>
>> TL;DR: A simple change can make Django's CSRF protection a little better;
>> an
>> additional, slightly less simple one, can also make it look better.
>>
>> Django's CSRF protection scheme is a bit unusual; unlike most such
>> schemes, it
>> does not rely on a value stored in the server that needs to be matched by
>> a
>> submitted token and is replaced with every submission, but rather on a
>> constant value stored in a cookie. This generally works (for details of
>> how
>> and under what conditions exactly, see [1]), but has two minor problems:
>>
>> 1) It is unusual, and in particular diverges from what OWASP[2]
>> recommends[3];
>> as a result, security analysts often think it is not secure. They have
>> been
>> proven wrong in all cases members of core are aware of, but proving it
>> again
>> and again is a nuisance, and there may be bad PR related to this.
>>
>> 2) It carries a "second-order" vulnerability: If your site has been
>> compromised (XSS, Man-in-the-middle, or server compromise) then you become
>> persistently vulnerable to CSRF. All of these vulnerabilities are way
>> worse
>> than CSRF and render all CSRF protection schemes worthless while they
>> last;
>> the point is *not* that they allow CSRF, but rather that they allow CSRF
>> to be
>> performed after the main hole has been plugged. This is because the
>> attacker
>> can use the main vulnerability to "steal", or even set, csrftoken cookie
>> values, which they can then use later. After a successful attack of this
>> magnitude, you need to reset the csrftoken cookies of all users, and this
>> is
>> neither obvious nor straightforward to do.
>>
>> Django's unique scheme does have two advantages over the more common
>> solutions, which we would like to keep:
>>
>> 1) It is not tied to sessions, users, or site-stored per-user data,
>> allowing
>> CSRF protection to a wider range of users
>>
>> 2) It avoids the problem of having only one "current" token, which causes
>> the
>> submission of one form to invalidate forms open in other browser tabs.
>>
>> To improve on both problem issues, while keeping the advantages, I suggest
>> the
>> following modifications:
>>
>> a) Use a signed cookie for csrftoken -- using Django's existing signing
>> facility[4], this means signing the cookie with the SECRET_KEY from the
>> settings; so that an attacker cannot set arbitrary cookies, and changing
>> the
>> SECRET_KEY after a compromise immeiately invalidates csrftoken cookies.
>>
>> b) Optionally allowing time-limited CSRF tokens. Such tokens will be
>> generated
>> by adding a parameter of maximum age to the csrftoken tag, and by marking
>> view
>> methods (specifically with a decorator, or globally with a setting) as
>> requiring timed tokens. When this is used, the posted token value will
>> need to
>> be different from the cookie value -- to keep advantage 2, the cookie will
>> still be constant, and expiry time will only be present in the submitted
>> token[5]. This method breaks the current way we do CSRF-protected AJAX, so
>> it
>> will likely stay optional (and opt-in).
>>
>> As you may guess, signing the cookie adds an actual iota of security.
>> Adding
>> expiry adds very little -- if an attacker has access to the cookie, they
>> can
>> usually just ask the site to generate valid tokens for them, so getting
>> any
>> real protection will require annoyingly short expiry times. But the fact
>> that
>> an attacker needs this extra step makes it a tiny bit harder for them and
>> makes their actions a tiny bit more detectable; and having a constantly-
>> changing CSRF token may make the whole thing look a little better to naive
>> analysts.
>>
>> I had some help and guidance in drafting this proposal -- you can credit
>> Donald Stufft, mostly, for any egregious blunder I didn't make. I am still
>> responsible for the ones I did make.
>>
>> Your comments are welcome,
>>
>>         Shai.
>>
>>
>> [1]  https://docs.djangoproject.com/en/dev/ref/contrib/csrf/ -- in
>> particular,
>> "how it works" and "limitations"
>>
>> [2] https://www.owasp.org
>>
>> [3]
>> https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29_Prevention_Cheat_Sheet
>>
>> [4] https://docs.djangoproject.com/en/dev/topics/signing/
>>
>> [5] django.core.signing.TimestampSigner signs content with the time of the
>> signature, and then takes a max_age in its unsign() method; the suggested
>> method would go the other way around, timestamping the token with the time
>> of
>> expiry, to allow checking without using data stored on the server (and to
>> allow different forms to use different max-age values).
>>
>> --
>> You received this message because you are subscribed to the Google Groups
>> "Django developers" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to [email protected].
>> To post to this group, send email to [email protected].
>> Visit this group at http://groups.google.com/group/django-developers.
>> For more options, visit https://groups.google.com/groups/opt_out.
>>
>>
>
> --
> You received this message because you are subscribed to the Google Groups
> "Django developers" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> To post to this group, send email to [email protected].
> Visit this group at http://groups.google.com/group/django-developers.
> For more options, visit https://groups.google.com/groups/opt_out.
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/django-developers.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to