9 ms·
Running Rails? Defend yourself against BREACH
- Denzel 13y agoGreat 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.
- jwilliams 13y agoFirst 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/ConditionalGet.html 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.
- bradleybuda 13y agoGreat idea; I was worried about breaking ETags but I think that would work. I'll test it and update the gem appropriately.
- jwilliams 13y agoActually, 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.
- lnanek2 13y agoWonder 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.
- deleted 13y ago[deleted]
- logical42 13y agoI'd downvote this if I could.
- deleted 13y ago[deleted]
- IvyMike 13y agoIt 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.
- ZaneA 13y agoExcept that this isn't specific to Rails at all, this is just a method for combating it if you are using Rails.
- samhamilton 13y agoThanks for getting this out so fast! Do you guys have plans to PR these changes back in Rails?
- bradleybuda 13y agoYep. 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.
- StavrosK 13y agoIt will probably make the attack a few orders of magnitude harder, but it'll still be feasible if you don't rate-limit requests.
- xs_kid 13y agoThere are any workaround for other web frameworks like Django or Padrino?
- beambot 13y agoI'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...
- btilly 13y agoThe first version of the attack, yes. But as http://arstechnica.com/security/2013/08/gone-in-30-seconds-new-attack-plucks-secrets-from-https-protected-pages/ 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.
- homakov 13y agoobviously second version (when CSRF token is stolen) is not possible to mitigate.
- btilly 13y agoThere 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.
- homakov 13y agoXOR-based masking, yes, but I thought we were talking about currently common systems. Until BREACH nobody masked tokens, did they?
- bijupunalor 13y agothis site looks like a shameless ripoff of git-scm.com/blog :( sad!, hire some designers?
- rwg 13y ago"A shameless ripoff"? Seriously?! http://i.imgur.com/r8mDlVU.png http://i.imgur.com/r8mDlVU.png
- xs_kid 13y agoThe author already opened a PR in rails: https://github.com/rails/rails/pull/11729 https://github.com/rails/rails/pull/11729 IMO looks great so far
- pygy_ 13y agoMore 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 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
- chrislaco 13y agoDoes anyone know, or seen info about whether enforcing client certificates mitigates/makes easier/harder the use of BEAST/CRIME/BREACH against servers?
- dlitz 13y agoI 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.
- fooyc 13y agoThe 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.
- homakov 13y agowow, so wrong. where did you find that?
- bradleybuda 13y agoYou're absolutely right - I screwed that up. I'll update the README appropriately.
- homakov 13y agohttps://gist.github.com/homakov/6147227 https://gist.github.com/homakov/6147227 thoughts?