CSRF protection bypass due to Google analytics and weird server cookie parsing
hackerone.com
hackerone.com
> cookie = "Cookie:" cookie-version 1*((";" | ",") cookie-value)
> Note: For backward compatibility, the separator in the Cookie header is semi-colon (;) everywhere. A server should also accept comma (,) as the separator between cookie-values for future compatibility.
https://www.ietf.org/rfc/rfc2109.txt
(I believe part of the issue was that MIME of headers describes how to deal with multiple headers with the same name, which is by concatenating them with commas, and that spec was the basis for the definition of HTTP headers.)
Seeing as how it's a combination of an issue in the web server parsing cookies, and the client setting malicious cookies, I'm not sure which party should be responsible for the bounty.
That's it. That one property.To add cookies, modified cookies, delete cookies, whatever, you do an assignment. To read all the cookies, you do a read.
That's it. That's the API.
One more thing: Cookies are limited to 4KB total due to the HTTP/1.1 specification.
I sent information about this vulnerability to: 1) Google (2 fix in Google Analytics) 2) Django / Python (https://hg.python.org/cpython/rev/270f61ec1157) 3) Twitter (changed CSRF protection) 4) Instagram [Facebook] (sent me to Django)
Google Chrome Version 42.0.2311.135 m on Windows 7 64bit
For example, Cookie: SHA1(salt + secret), then CSRF-TOKEN header/value is taken, the salt extracted, hashed against the server-side secret and compared.
Really the difference is that you compare the user's response to a known value on the server rather than two values in the same request body which cannot be independently verified.
Keep in mind that if you don't change the client's view of the token on every page load (using some kind of salt), you are potentially vulnerable to CRIME/BEAST.
Most advanced CSRF schemes use some crypto primitives in a manner like client-side sessions work (Enc+Mac on the server, give token to user, Validate Integrity+Dec on the server when you get it back), or HMAC some user meta-data. This allows you to distribute the key and then any server with the key can validate the token without needing to know the token in advance.
I've written a blog post about a bunch of types of CSRF schemes and their pros and cons, but never published it. Is this interesting enough for me to publish?
Definitely. Having looked myself, I can tell you there aren't many resources online that get this right.
HSTS partially prevents the MITM-over-http, but not 100% the person doing the MITM potentially controls the clock (NTP is unauthenticated). Unless you do HSTS by whitelisting the domain in the browser.
Security is hard :(
If you create a session for the logged-out user, you must be careful about not recycling the same session once logged in or you expose yourself to session fixation.
http://stephensclafani.com/2011/04/06/oauth-2-0-csrf-vulnera... and http://homakov.blogspot.com/2014/01/two-severe-wontfix-vulne... explain the issue pretty well.
One can always replace it with something that is vulnerable, so there are probably Django sites out there with this problem. But if you never thought deeply about it, your site is fine... What's a feature that I really love about Django, you'll see that same same phrase "if you never thought deeply about it, your site is fine" for lots and lots of security problems.
What I don't get is how is it possible to do CSRF with cookies? Aren't cookies always shared between simultaneous browsers sessions? Isn't the entire point of CSRF to avoid that?
This is not true. The default Django CSRF protection uses cookies for the session store[1]
> What I don't get is how is it possible to do CSRF with cookies?
The same as any other CSRF mechanism :)
1. You provide the user a (preferably per-request vs. BREACH) token, often in a hidden form field. The field being hidden is primarily for UX reasons.
2. You store a copy of that token in a session store. This is often a cookie due to the convenience of cookies (no server state required), but can be in a server-side store (memory, Redis, RDBMS, et. al).
3. Upon any non-idempotent HTTP method (anything that's not GET/HEAD/OPTIONS) you compare the token in the submitted form to the value stored in the session.
The benefits are that you don't have to maintain server state. The downside is that you're transmitting your token over a channel at risk of MITM. Using authenticated cookies helps as any attempt to modify both the form value AND cookie value (i.e. so they match) should fail when you verify the MAC on form submission.
By default, Django's cookies are authenticated.
[1] https://github.com/django/django/blob/master/django/middlewa...
I've had the GA domains redirected to 0.0.0.0 via HOSTS file for... ever since GA started to exist, and I haven't seen any specific messages to that effect. It'd make sense that some would use JS to detect this, but I have that disabled by default.
Maybe it's because I see a lot of other "broken" sites in my daily browsing due to that, and I don't really need to find out why - if a site isn't giving the info I need, I go back to the search results and to the next one.