Running Rails? Defend yourself against BREACH
blog.meldium.com
blog.meldium.com
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.
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.
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.
" 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.
IMO looks great so far
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* 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.
Isn't that the point of CSRF? That's the advice Django provides anyway...
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.
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.
In that case it would be impossible to predict common text in the CSRF based on past compression rounds.
Until BREACH nobody masked tokens, did they?
Do you guys have plans to PR these changes back in Rails?
Deleted comment
Deleted comment
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.