

Running Rails? Defend yourself against BREACH - bradleybuda
http://blog.meldium.com/home/2013/8/2/running-rails-defend-yourself-against-breach

======
Denzel
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.

------
xs_kid
The 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_
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](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
Does anyone know, or seen info about whether enforcing client certificates
mitigates/makes easier/harder the use of BEAST/CRIME/BREACH against servers?

~~~
dlitz
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.

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

~~~
rwg
"A shameless ripoff"? _Seriously?!_

[http://i.imgur.com/r8mDlVU.png](http://i.imgur.com/r8mDlVU.png)

------
samhamilton
Thanks for getting this out so fast!

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

~~~
bradleybuda
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.

~~~
StavrosK
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.

------
homakov
[https://gist.github.com/homakov/6147227](https://gist.github.com/homakov/6147227)

thoughts?

~~~
kondro
What about non-JS based authenticity tokens?

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

------
fooyc
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.

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

------
jwilliams
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...](http://api.rubyonrails.org/classes/ActionController/ConditionalGet.html)),
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
Great idea; I was worried about breaking ETags but I think that would work.
I'll test it and update the gem appropriately.

~~~
jwilliams
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.

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

~~~
beambot
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...

~~~
btilly
The first version of the attack, yes.

But as [http://arstechnica.com/security/2013/08/gone-
in-30-seconds-n...](http://arstechnica.com/security/2013/08/gone-
in-30-seconds-new-attack-plucks-secrets-from-https-protected-pages/) 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
obviously second version (when CSRF token is stolen) is not possible to
mitigate.

~~~
btilly
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.

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

Until BREACH nobody masked tokens, did they?

~~~
btilly
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.

~~~
homakov
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

