Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Running Rails? Defend yourself against BREACH (meldium.com)
102 points by bradleybuda on Aug 3, 2013 | hide | past | favorite | 34 comments


First of all, thanks for for getting this out there.

The Length Hiding piece protects all content, but only really slows the attack (as you mention!).

The problem is this implementation breaks Rails' Conditional GET (Actually Rack's) -- which returns 304 Not Modified if the content is the same. Now that the content varies, normal usage will get a 200 and the full response every time.

It depends on the Application, but in most cases this will be a reasonable increase in overall bandwidth (for normal use, not the attack). Probably more of an increase than you'd encounter by turning off gzip - which completely defeats the attack rather than just making it more difficult, as Length Hiding does.

The workaround is to use ETags (See: http://api.rubyonrails.org/classes/ActionController/Conditio...), which will use the tag rather than the content to determine 304s. I'd suggest this should be recommended if you're using Length Hiding.

Edit: Actually another workaround might be to put your Middleware after the relevant middleware Rack::ConditionalGet, Rack::ETag. Right now it's at the top of the Middleware chain.


Great idea; I was worried about breaking ETags but I think that would work. I'll test it and update the gem appropriately.


Actually, it's a harder workaround than I was suggesting. When the ETag isn't explictly set, the full body of the middleware chain is generated every single time, irrespective of the Conditional Get.

You want the ETag generated without the Length Hiding, which isn't the way Rack::ETag works. It digests the whole content - it's implementation calls upstream first, so it effectively ensures it's always at the end of the middleware chain.

You'd need to extend/replace/otherwise hook into Rack::ETag, which is a bit more surgical.


Wonder how easy it would be to turn off gzip on just potential attacks. It takes a lot of requests to execute the attack after all. So an example where each user only got their response gzipped the first time for any URL would be safe. But then the site would slow down for them later. So you'd have to pick some sort of reset metric that prevented efficient attacks, but still gave users compressed data most of the time.

Another piece of low hanging fruit would be to change the session cookie every request. It isn't a big deal for most servers to update the session ID and send a cookie down each request. Meanwhile it would hurt attacks going after the session ID by methods like this that need a lot of requests with the same value a lot.


The following sentence seems really wrong:

" Setting the X-Frame-Options header can make it harder for an attacker to carry out this attack (by making it impossible to put your site in an iframe). "

Even with X-Frame-Options, the browser still makes a request (else, how can it see the X-Frame-Options header ?). X-Frame-Options only prevents display and execution, not requests.


You're absolutely right - I screwed that up. I'll update the README appropriately.


wow, so wrong. where did you find that?


The author already opened a PR in rails: https://github.com/rails/rails/pull/11729

IMO looks great so far


More general mitigation strategies:

The random length padding could perhaps be added to the compressed payload rather than the source document. Sensible decoders should ignore the padding, but it may depend on the decompression code and requires thourough testing.

Another option is to append a random length HTTP trailer header, sending the response in chunked mode. However, the spec says that you can only use chunked mode when the request specifies that the client supports it, and I don't have any idea of the browser support for said mode (you could refuse to serve content to clients that don't support chunked mode).

The second option can also be used to slow down CRIME if the payload is not compressed (beside TLS or HTTP 2.0 compression), or can't be padded for some reason.

The main drawback of chunked mode is that the client doesn't get to know the file length in advance.

These methods could be implemented at the reverse proxy level rather than the app level. That way, the Rails conditional GET would still work.

--

[0] http://en.wikipedia.org/wiki/Chunked_transfer_encoding

Example of a chunked transfer response, with a trailer:

    HTTP/1.1 200 OK
    Transfer-Encoding: chunked
    Trailer: My-Test-Trailer
    D\r\n
    All your base\r\n
    B\r\n
     are belong\r\n
    6\r\n
     to us\r\n
    0\r\n
    My-Test-Trailer: something\r\n
    \r\n



What about non-JS based authenticity tokens?


Not everyone supports non-JS user but yes, it's a minus.


There are any workaround for other web frameworks like Django or Padrino?


I'm not sure - but if you're concerned* you can turn off gzip compression for HTML. At least until a longer term fix is available. Turning off gzip/compression negates the attack irrespective of the framework.

* it's probably right to be concerned, but worth keeping in mind that this attack still requires a fair bit of access (to your traffic), planning (working out the vulnerable data) and intent.


I'm a bit confused.... In the mitigation section, the paper states: "However, we remark that requiring a valid CSRF token for all requests that reflect user input would defeat the attack."

Isn't that the point of CSRF? That's the advice Django provides anyway...


Typically CSRF tokens are only required for state-changing requests - POSTs, PUTs, DELETEs.

They're broadening that recommendation also to include pages that reflect input. Think GET requests that take query string parameters. So e.g. https://google.com/search?q=pajamas would become https://google.com/search?q=pajamas&csrf=etcetc.

It seems like a pretty impractical mitigation to me. For one thing, it would make it very difficult to share links; a link containing my CSRF token wouldn't work for you. It would also make it much easier to give up your CSRF token. We would need to retrain people to think of the URLs they're viewing as personal and secret.


The first version of the attack, yes.

But as http://arstechnica.com/security/2013/08/gone-in-30-seconds-n... makes clear, another variant lets you get the CSRF token, and after that the CSRF token is no protection at all against anything else that people try.


obviously second version (when CSRF token is stolen) is not possible to mitigate.


There is a way that the CSRF attack could be prevented. And that is if only every other byte of the CSRF token was part of the token, and the others were random every time.

In that case it would be impossible to predict common text in the CSRF based on past compression rounds.


XOR-based masking, yes, but I thought we were talking about currently common systems.

Until BREACH nobody masked tokens, did they?


Nobody did, but that is how life goes. An attack is found. A defense is found. And you can't build a secure system without knowing all of the attacks and corresponding defenses.


i wouldn't call it a proper defense, rather a work around. besides CSRF tokens there are lots of secret strings, and it's not website's problem to avoid wiretapping


Django is vulnerable to cookie forcing. BREACH is not needed, CSRF token can be replaced with active MITM


Thanks for getting this out so fast!

Do you guys have plans to PR these changes back in Rails?


Yep. I'm sending a patch for the CSRF token masking change shortly. I'm less sure about the length hiding change; it feels like an ugly hack, but we put it in because it's the least awful solution that the paper presents. I'm curious to find out exactly how effective the length hiding is one the PoC code is released.


It will probably make the attack a few orders of magnitude harder, but it'll still be feasible if you don't rate-limit requests.


Does anyone know, or seen info about whether enforcing client certificates mitigates/makes easier/harder the use of BEAST/CRIME/BREACH against servers?


I don't think they'd be much help. Even with client certificates, information will still leak via compression, and so an attacker will still be able to get CSRF tokens and then use them then forge requests via the user's own browser.


Great to see such a quick response! Definitely a cause for pause. I plan to sit down with the paper tonight to fully understand the implications.


[deleted]


I'd downvote this if I could.


[deleted]


It isn't a Rails specific vulnerability. So if you don't run Rails you're actually worse off because you don't get this (tiny) amount of protection.

And even if it were a Rails specific problem, "Don't run Rails to avoid any issue with Rails" is obvious, and is unhelpful to everyone.


Except that this isn't specific to Rails at all, this is just a method for combating it if you are using Rails.


this site looks like a shameless ripoff of git-scm.com/blog :( sad!, hire some designers?


"A shameless ripoff"? Seriously?!

http://i.imgur.com/r8mDlVU.png




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: