Apparently that has all changed. The details are currently very limited (or I just haven't found them). This is what is provided at the django and ruby on rails security update pages:
Recently, engineers at Google made members of the Ruby on Rails development team aware of a combination of browser plugins and redirects which can allow an attacker to provide custom HTTP headers on a request to any website. This can allow a forged request to appear to be an AJAX request, thereby defeating CSRF protection which trusts the same-origin nature of AJAX requests.
Michael Koziarski of the Rails team brought this to our attention, and we were able to produce a proof-of-concept demonstrating the same vulnerability in Django's CSRF handling.I'm very curious to find out more. Is a proof of concept available? What browser plugins are required for this attack? The potential exposure must be large because both frameworks have released a "backwards-incompatible" patch.
This is technically backwards-incompatible, but the security risks have been judged to outweigh the compatibility concerns in this case.
-Michael Coates - @_mwc
Ouch, this could be really bad. Some very high profile sites use this approach without using either Django or Ruby on Rails. In fact, I've recently used this very approach myself because this is the simplest way to secure an AJAX application.
ReplyDeleteI'm guessing that they're not releasing the details until the plugin(s) in questions have been patched. Unfortunately, It's not clear whether only custom headers like X-Request-Header can be added or if existing headers like Content-Type can be changed as well.
ReplyDeleteSome frameworks I've seen require that POSTs have a Content-Type of text/xml which (I had thought) wasn't possible to do cross-domain. Browsers generally allow only text/plain or application/x-www-form-encoded.
This may (or may not) cause trouble for websites that store anti-CSRF tokens in cookies. Can't tell without a proof-of-concept.
ReplyDeleteThanks for brining this to our attention Coates. How about some OWASP love though?? When implementing CSRFGuard 3.0, I made the assumption that a scenario like this would occur. To mitigate the risk, CSRFGuard injects a CSRF prevention token in all XMLHttpRequests sent to the server, all of which was done before the Django fiasco!
ReplyDeleteGo CSRFGuard!
CSRFGuard is in need of testers - support the project!
http://www.owasp.org/index.php/Category:OWASP_CSRFGuard_Project
Hey, I'm the security coordinator for ruby on rails. We're keeping the details reasonably close to our chest for exactly the reasons you've outlined. Many non rails sites made that same assumption, to have it destroyed was a horrible surprise for us. I'm sure it'll surface pretty promptly but we didn't want to feed metasploit etc before people have a chance to take corrective action. Not to sound dramatic, but everything has changed.
ReplyDeletealbino, cookies are fine, they can't read cookies, only forge headers.
paul stone, 'yes' they can forge any old header but the browser still sends content-type with post requests so whether that's exploitable would depend on how the server parses duplicate headers. For what it's worth, we used to rely on request content-type and no longer do.
Koz, I was wondering whether it could be used to forge a cookie header with a CSRF-token in it in such a manner that the server thinks the faked CSRF-token is the real one, and validates it against the token in the request body. If this possible, the attacker wouldn't need to know the value of the real token.
ReplyDeletealbino, I just tested this with Django - I took a normal POST request that had a CSRF cookie and POST parameter. Then I appended another Cookie: header at the end. It looks like the second Cookie header overwrites the first one.
ReplyDeleteDjango accepts any value for the CSRF token - as long as the cookie value matches what's posted in the form. I can't fully test this because I don't know how the cross-site header vulnerability works, however based on what Koz said it sounds like Django's CSRF system may still be vulnerable even with this fix (and that includes normal POSTs as well as AJAX ones).
I'm not sure how the Rails CSRF system works - hopefully they store the secret CSRF value in the session like most other frameworks.
Interesting. Unless I've misunderstood something, this is really quite significant, and we've just ruined our chance of finding out how this arbitrary header forging works anytime soon :)
ReplyDeleteDetails of how to perform the header forging are explained here
ReplyDeleteForging cookie headers doesn't appear to be possible, at least not until someone find a bypass for flash's header blacklist.
With the info linked above I found the relevant Firefox bug: https://bugzilla.mozilla.org/show_bug.cgi?id=573873. It's too bad that Adobe has been sitting on this for three years but it looks like the problem is mostly gone now. The solution that went into Firefox 3.6.14/3.5.17 was simply disallowing 307 redirects. Firefox 4 then modified NPAPI to give plugins more control of redirects. I guess that other browsers will implement this NPAPI extension soon if they haven't done so already.
ReplyDelete