BREACH (Browser Reconnaissance and Exfiltration via Adaptive Compression of Hypertext) is a security exploit against HTTPS when using HTTP compression. BREACH is built based on the CRIME security exploit.

One of the most effective ways to mitigate BREACH is to turn off HTTP compression. However, this reduces performance. Other ways include randomizing secrets (that is, sensitive data) per request or masking secrets, protecting vulnerable pages with CSRF. However, these methods are implemented on the application level, not on the web server level. Another method is Length Hiding. The idea of the method is to append a randomly generated data (for example, a HTML comment) to the end of HTML response to hide correct length and make it difficult for attackers to guess secret information.

Nulab has implemented Nginx Length Hiding Filter Module which implements the last method. However, for me it was interesting to achieve the same effect without any third party modules (as far as I can tell, Nulab’s module is packaged neither by Debian nor Ubuntu, and I am too lazy to rebuild nginx myself every time).

This is what we have (nginx-extras module):

Modules we need:

  1. Embedded Perl (ngx_http_perl_module).
  2. Either Addition (ngx_http_addition_module) or Substitution (ngx_http_sub_module) module.
  3. SSI (ngx_http_ssi_module) module (optionally).

Embedded Perl + Substitution Module

The ngx_http_sub_module module is a filter that modifies a response by replacing one specified string by another.

First, we need to define a special variable somewhere in http block:

This code generates a random string ($string) as a HTML comment consisting of letters A to Z, a to z, and digits 0 to 9 (@chars) 256 to 2048 ($len) characters long.

Now we need to insert this random string:

After saving and reloading nginx, the result will look like this:

Embedded Perl + Addition Module

The ngx_http_addition_module module is a filter that adds text before and after a response.

Because of the above, we have less freedom as to where to put our random data: we can either put it before or after , but not in any other place. And if we are going to keep the HTML valid, we can only insert a comment.

We need to define two locations:

This one instructs nginx to append data received from /add_random_data subrequest to the data from the main request.

Now the handler for /add_random_data:

After saving and reloading nginx, the result will look like this:

Any of the Above + Server Side Includes

The ngx_http_ssi_module module is a filter that processes SSI (Server Side Includes) commands in responses passing through it.

Server Side Includes can be very useful if you are heavily relying upon a static cache (i.e., nginx’s FastCGI cache, Cloudflare, etc). SSI allows for inclusion of dynamic fragments into otherwise static page (you only need to configure your cache not to cache data from those SSI locations; in case of Cloudflare, you also need to turn off HTML minification, as it strips all comments).

The idea is that the filter module returns an SSI comment like this:

Then the SSI module processes that instruction, and replaces it with the actual data.

The configuration will look something like this:

The handler for /add_random_data will be the same:

The result will look something like this:

Conclusion: nginx’s builtin modules are quite powerful; often, their power is more than enough to implement functionality you need without any third-party modules.

nginx: Mitigating the BREACH Vulnerability with Perl and SSI or Addition or Substitution Modules
Tagged on:                     

Leave a Reply

Your email address will not be published. Required fields are marked *