2

I have a backend for a mobile application that has to serve large JSON responses from time to time, the transfer would be greatly helped by enabling compression, especially when the user has bad coverage.

Googling it seems like enabling compression for HTTPS endpoints is a bad practice due to BREACH attacks, looking into BREACH attacks it seems like the easiest way to mitigate them is using a CSRF token.

Looking into CSRF tokens for mobile it seems like the consensus is that they are not vulnerable to it (found some resources stating that using a signed double submit cookie would make it possible to implement it for mobile apps, but it not being strictly necessary)

This leaves me wonder what is the best way to provide compressed data to a mobile application from a backend?

1
  • the key is to make sure each response is different. Any per-request response that includes something unique each time should help mitigate CRIME/BREACH attacks. That's what per-form anti-csrf tokens do.... it has a side-effect of helping with CRIME/BREACH. Just send the value in every response regardless of if you enforce validation. Commented Aug 12 at 18:29

4 Answers 4

8

BREACH is possible when:

  • the attacker can spoof many authenticated requests,
  • the application reflects user input in the response,
  • the response contains sensitive information.

Spoofing requests is typically done by luring the victim to a malicious site, and performing cross-site requests to the target site. This only works when the target site uses cookie authentication, or some other form of automatic authentication.

This is likely not possible in your mobile app. Even if you use cookie authentication, these cookies would be limited to your mobile app, and it wouldn't be possible for an attacker to trigger malicious requests from your mobile app.

BREACH is not necessarily mitigated by a CSRF token as typically used. In fact, CSRF tokens are typically the "sensitive information" obtained in the attack.

For websites, the risk of BREACH is greatly reduced by using Same-Site cookies, since this makes it harder for an attacker to send authenticated requests.

3

As others have pointed out, you probably don't have to worry about BREACH for this scenario. However, if you would still prefer to not enable compression at the protocol level (a reasonable concern if, for example, you currently or might later add a web client), there's another option: perform compression (of the large response to the mobile client, specifically) at the application level. That is, simply compress the big JSON blob using whatever codec (e.g. zip/gzip/bzip2/xz/lzw/etc.) you prefer, then set the result as the response body and transmit it as compressed data, and then decompress it on the client using the same codec.

Note that if you're going to do this, pick your codec and parameters carefully; some - especially for sufficiently large blobs - are computationally expensive enough during compression that you risk creating a denial-of-service threat against your server.

2
  • How would this help against BREACH? I am not sure why compressing the response in another layer would make a difference. It seems that you would still be vulnerable for BREACH when compressing the JSON in the application.
    – Sjoerd
    Commented Aug 14 at 8:02
  • BREACH requires that the attacker can hold the message mostly the same (though initially unknown), and make controlled changes to it (for example, by making slight changes to the URL path or query string). That's easy for requests, but generally not practical with responses, which are mostly out of the attacker's control and/or may change unpredictably. The request wouldn't be compressed, here; only the response, so it shouldn't be vulnerable.
    – CBHacking
    Commented Aug 18 at 5:40
2

Breach works because it’s basically makes tokens like the CSRF guessable.

And it’s only true mitigation is by not using compression at all.

How ever, that is only true for those part of a request that are actually containing secrets. (Remember, this could just be the cookie giving access).

1 mitigation which would help your problem would be chunked transfer / batch transfer.

Which would divide up the response into parts which hinder the guess ability and would speed up load times.

You could also include a field specific compression, especially if you use it to encapsulate an array or object response.

The main request wouldn’t be compressed, just part of it would be (remember that this would include something like a base64 scheme to keep the output html friendly and add the added burden of decoding an additional compression Client side).

As for what’s the best, only you can choose that (since that’s out of scope for this site). But I hope this Awnser gets you thinking about possible solutions.

7
  • You say "request" twice, where I think you mean "response"? The response is compressed, not the request. Doing partial compression could still be vulnerable to BREACH.
    – Sjoerd
    Commented Aug 14 at 8:05
  • @Sjoerd Partial compression shouldn't be vulnerable as long as you never compress secrets and attacker-controlled data together (using the same compressor dictionary). The compression oracle can only work when it produces a match between a secret and some chosen plaintext; separating the two should block it altogether, shouldn't it?
    – TooTea
    Commented Aug 14 at 9:12
  • Why would the output need to be "html friendly"? Did you mean HTTP friendly? If so, why? HTTP is perfectly fine with transporting arbitrary binary data, so there's nothing stopping you from sending e.g. an octet-stream which starts with a bit of uncompressed JSON followed by binary gzip data.
    – TooTea
    Commented Aug 14 at 9:15
  • @TooTea, if you are going to decode the compressed JSON object, it must be using characters allowed to be in JSON. Which is what I think you missed in my suggestion, namely in that scenario you are only compressing part of the request, not the full thing. If you are compressing the full response than you introduce the potential pitfalls of BREACH. It would indeed be fine to just send it as an octet stream in that case. JavaScript won’t proces it as anything but binary data though. And certainly not as JSON.
    – LvB
    Commented Aug 14 at 11:55
  • @Sjoerd there is no real difference between a request and a response, just the flow is different. When ambiguous I tend to use “Request” as that is more generic. And as TooTea pointed out, it’s the shared dictionary that reveals data, if you don’t mix the dictionaries than BREACH doesn’t apply.
    – LvB
    Commented Aug 14 at 11:59
2

Enabling compression at the HTTP or TLS level is indeed risky, but specifically compressing the JSON documents included in the responses can be secure under certain circumstances.

So you should compress the JSON document on the server and then decompress it in the mobile app. To ensure that no attacks against the compression can happen, use the following approach.

  • Try to keep all sensitive data out of the compressed document. If you do have sensitive data, split the document into an uncompressed and a compressed part. Only the uncompressed part should contain sensitive information.
  • Don't let the user inject arbitrary data into the compressed document (e.g., through a URL parameter or the request body). Compression attacks work by guessing parts of the original content, injecting this data into the content and then observing length changes of the compressed output. This should not be possible with the JSON documents.
  • For defense-in-depth, use a countermeasure like Heal the BREACH which randomly changes the size of the compressed output to prevent attackers from gaining any information from the size.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .