Thanks for much for this contribution.  I don't feel particularly qualified
to review it, but there's are particular bits where general django
knowledge (or even just a second pair of eyes) will help, let the know.
On Aug 3, 2014 9:48 PM, "Adam Brenecki" <[email protected]> wrote:

> Hi all,
>
> So, a while ago, BREACH happened, and Django's CSRF implementation was
> vulnerable, as was Rails'. The paper that discussed it described a
> mitigation (and a Rails patch had already been made), so I implemented that
> same mitigation in a Django patch. Discussion on the Trac ticket has
> stalled, and I've been told this is the place to go.
>
> Disclaimer: although I understand enough about it to write the patch, *I'm
> not a security person* - the reason I'm posting here is that I'm hoping
> to get an answer from someone that *is* a security person as to whether
> I'm on the right track.
>
> To jog your memories (and also in the hope that if I'm misunderstanding
> the problem, someone will correct me), the short version of BREACH is: an
> attacker forcing a user to visit a HTTPS page that a) is gzipped, and b)
> contains *in the response body* a secret (in our case, the CSRF token in
> the form), as well as user input (e.g. reflected URL parameters), then
> observing the size of the HTTPS responses. When the user input partially or
> completely matches the secret, the compressed length is slightly shorter,
> and the attacker can use this to guess the secret byte-by-byte.
>
> In section 3 of the paper, the authors describe a variety of mitigations.
> One of them is to, on each request where a secret S should appear,
> generate a new one-time pad P and instead write P + xor(P, S) in the
> response. (The paper also describes other mitigations, but this is the most
> feasible¹.)
>
> My understanding is (and I'll reiterate here I'm not a security person)
> that this should make S impossible to deduce via BREACH, as it doesn't
> appear directly anywhere in the response. As P takes on a new value with
> every request, it simply can't be deduced by any method that involves
> making many requests; therefore the same thing will happen to xor(P, S).
> (I think the fact that P changes every request might have been a point of
> confusion in the Trac discussion; there's a lot of comments there talking
> about trying to deduce P).
>
> The patch I've written implements this mitigation, with one difference:
> instead of using xor, it uses a Vigenère cipher (as suggested by FunkyBob),
> as xor was creating non-printable characters which caused problems. I think
> this should be OK as Vigenère is commonly used for one-time pads and does
> more or less the same thing to characters that xor does to bits.
>
> This is pretty much what django-debreach does, except that *it* uses AES
> instead of xor (i.e. the output is K + AES(K, S).). However, this adds
> processing load to every request and a dependency on PyCrypto, and as far
> as I can tell this doesn't actually add any benefit over xor/Vigenère.
>
> So, in summary, I think I'm doing nearly exactly what the paper says, and
> I think it effectively makes the attack practically impossible, but I'd
> love to hear from someone who has a better idea than I as to if I'm
> actually correct on all of this.
>
> Thanks,
> Adam
>
> The Trac ticket: https://code.djangoproject.com/ticket/20869
> My pull request: https://github.com/django/django/pull/1477
> The original paper:
> http://breachattack.com/resources/BREACH%20-%20SSL,%20gone%20in%2030%20seconds.pdf
> (the relevant bit is section 3.4 at the bottom of page 10)
> The related Rails pull request: https://github.com/rails/rails/pull/11729
>
> ¹ Section 3.4 describes the mitigation I implemented. Section 3.1
> describes fuzzing the lengths of each response by appending random lengths
> of garbage data, then immediately dismisses this method as ineffective;
> Russell Keith-Magee tells me that a discussion within Django reached the
> same conclusion about this one. Apart from those two, they're all things
> like rate limiting and separating secrets from user input, which don't seem
> to me like things we can enforce on a Django level.
>
> --
> 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.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/django-developers/66fb5b2b-5f18-4244-92fb-2427b5b63aa8%40googlegroups.com
> <https://groups.google.com/d/msgid/django-developers/66fb5b2b-5f18-4244-92fb-2427b5b63aa8%40googlegroups.com?utm_medium=email&utm_source=footer>
> .
> For more options, visit https://groups.google.com/d/optout.
>

-- 
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.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/CAMGywB4h21JyQiu6-nd0mQ2nPoA3A3ewgNvjPBPixScv%2BOpiaQ%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to