Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Switch off all GZIP..? That feels very extreme, I'm sure there are better workarounds than that one.

EDIT: The following workarounds should be very simple to implement and seem like more viable alternatives for production?

  Length hiding (by adding random amount of bytes 
    to the responses)
  Rate-limiting the requests
Mitigations 6 and 7 taken from http://breachattack.com/


All these framework-vendor guides will recommend switching off Gzip, because it's a content-neutral workaround; it works everywhere, for every instance of the attack, no matter how you've coded your app. There are more specific workarounds, but they require changing how you encode secrets into your page, so there can't really be a vendor guide on how to do that; the vendor doesn't know how and where your app sticks secrets into its views, after all.


I'm sure everyone is going to come up with workarounds that re-enable compression, but they'll be context-dependent and will involve code; in the meantime, the attack is straightforward and viable. Think of disabling compression as a stopgap.


Definitely think about it before just doing it though...

Disabling compression can break some apps. Especially when they rely on huge compression ratios for text (5-10 times ratio is common for with much json for example). So that is not an app agnostic work around. For example, a 100k of json request, can turn into a 1MB json request. The more data required to send, the more chance of error - especially on 3g/2g networks.

For many high end projects, just disabling compression without regard to testing or having an idea of what the application is doing would get you fired or taken to court.

Not only would this break apps, but it would also lose business in that there is evidence from Amazon and others that every 100ms extra latency can cost 1% in sales.

From SPDY whitepaper: "45 - 1142 ms in page load time simply due to header compression". Remember that headers use the upload part of the link... which means too many headers and you can saturate the upload, therefore making the whole internet connection stall for everyone using it. Common upload limits are only 5-10K/second, so excessive headers combined with many requests can easily DOS many internet connections.

I spend a lot of time optimising websites for these reasons, and disabling compression could add 20 seconds of load time for a good percentage of users.

So, for many apps, turning off compression is no solution at all. You might as well just disconnect your app from the internet - that will also give you a secure and broken app.

A proper risk, and impact analysis should be done first. Too often quick hot fixes to security issues just break things or even make things less secure.


Yeah turning off compression completely is kind of crude but it works without having to go into app-specifics, I'm sure the Django folks are on it ;). When it comes to things like CSRF tokens, probably secret masking (4) is the easiest to implement? so something like

  import uuid
  csrf = '42be455e20e64d7294eee8d1806d14a9'
  p = uuid.uuid4().hex # random response-specific pad
  xord = "%2x" % (int(csrf, 16) ^ int(p,16))
  request_token = "%s%s" % (p, xord)
  print "<input type='hidden' name='token' value='%s'>" % request_token
  v_unxord = "%2x" % (int(request_token[len(request_token)/2:], 16) ^ int(request_token[:len(request_token)/2], 16))
  if ( v_unxord == csrf ): print "yay, valid CSRF" # constant_time_cmp


Length hiding was shown to be ineffective in the article (by adding random noise). Perhaps a fixed length response would work better- or perhaps one that is heavily quantized? Really, production environments are not the place to try un-vetted academic crypto research.


> Really, production environments are not the place to try un-vetted academic crypto research.

A very salient piece of cautionary advice. Disable gzip to protect prod. Figure out what to do to allow compression off prod, and engage the devs of your stack/framework to do this correctly.


You can still safely compress your static files. So, assuming that you don't send any secrets in your CSS, JS etc., you can configure your server to enable gzip only for these resources.

For example, when using nginx and with gzip off globally, you can do :

    location /static/ {
        gzip on;
        ...
    }


Would this really work? Won't they be sharing cookies unless the static files are on a different domain?


Doesn't matter if they share cookies. Static files reflect neither user-supplied data nor secrets in their contents, so they can't be used in a BREACH attack.


Additionally, you should be serving static files from a different domain anyway so that you can get the performance gains from cookie-less requests.


Can you point out some more info/sources on these performance gains?



Would it be possible to just have some sort of dynamic compression scheme and not gzip when you'll potentially be transmitting sensitive information?


This. Suppose we could randomize Gzip levels differently in each response.


Randomizing Gzip levels (and random padding) only increases the number of samples you need to take.


We can also create one-time pads for tokens, so the number of samples will ramp up pretty so quickly which will make these kind of attack unfeasible.

And I guess we can tweak gzip Huffman tables so user inputs were poorly compressed compared to rest of the page content.


adding random amount of bytes to response may break your caching, in a variety of ways.


unlikely to affect you if you're already embedding CSRF tokens in your responses, which would defeat caching anyway. Curious if this response length fiddling will mitigate the attack, can anyone more knowledgeable than me confirm?


interesting point that CSRF tokens break caching. People can store it in cookie, and not put into the actual HTML.




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

Search: