Limit Decompression Attacks: Reverse Proxy Setup
This guide shows you how to configure reverse proxies and API gateways to defend against decompression-based attacks, such as ZIP bombs and gzip bombs, which can exhaust memory and CPU when a server expands maliciously compressed payloads. You’ll learn to set size limits, disable unnecessary compression, and apply request validation at the edge. No prior security expertise is required, but you should have administrative access to your reverse proxy or gateway and a basic understanding of HTTP headers.
What You’ll Need
- Access to the configuration file of your reverse proxy (e.g., Nginx, HAProxy, Apache) or API gateway (e.g., Kong, Traefik, Envoy).
- Knowledge of the service’s restart procedure (e.g.,
systemctl restart nginx). - Optional: a test client like
curlto verify behavior.
Step-by-Step
- Identify the proxy or gateway component. Determine which layer handles incoming requests. For Nginx, this is the
httporserverblock; for HAProxy, thefrontendorbackendsection; for Apache, theVirtualHostorDirectorycontext. - Disable request body compression if not required. Most proxies do not decompress request bodies by default, but if you have enabled it (e.g.,
proxy_request_bufferingwith gzip), turn it off. In Nginx, setproxy_request_buffering off;and avoid usinggzipon request data. In HAProxy, do not usecompressiondirectives on the request path. - Set a maximum request body size. This limits the compressed payload size. In Nginx, use
client_max_body_size 1m;(adjust size as needed). In Apache, useLimitRequestBody 1048576(bytes). In HAProxy, usemaxconnortimeout http-requestbut for size, usehttp-request deny if content_length gt 1048576. - Limit decompressed content size. If your proxy can inspect decompressed content (e.g., via a plugin like Nginx’s
ngx_http_gunzip_module), set a cap. For Nginx, usegunzip on;and thenclient_max_body_sizeapplies to the decompressed size, so set it appropriately. For Envoy, use thegzipfilter withmax_compressed_sizeandmax_uncompressed_size. - Reject requests with unexpected Content-Encoding. Only allow known encodings (e.g., gzip, deflate) and reject others. In Nginx, use
if ($http_content_encoding !~* "gzip|deflate") { return 415; }(though Nginx discouragesif, this is acceptable in server context). In HAProxy, usehttp-request deny if hdr(content-encoding) -m not -i gzip deflate. - Enforce a compression ratio limit. Some proxies allow a maximum compression ratio. For example, in Envoy’s gzip filter, set
compression_levelandmax_compressed_size. In Nginx, you can use thengx_http_gunzip_modulebut it doesn’t directly limit ratio; instead, you can use a third-party module or rely on the size limits. - Add request timeouts. A decompression bomb can take a long time to process. Set a timeout for receiving the full request body. In Nginx, use
client_body_timeout 10s;. In HAProxy, usetimeout http-request 10s. - Apply rate limiting. Limit the number of requests per IP to reduce the impact of automated attacks. In Nginx, use
limit_req_zoneandlimit_req. In HAProxy, usestick-tableandhttp-request track-sc0. - Test with a small compressed payload. Use
curl --compressed -H "Content-Encoding: gzip" --data-binary @test.gz http://your-proxy/to verify it passes. Then create a large compressed file (e.g., a 1GB file compressed to 1MB) and confirm it is rejected. - Monitor logs. Check proxy logs for 413 (Request Entity Too Large) or 415 (Unsupported Media Type) responses. Adjust limits based on legitimate traffic.
Common Mistakes
- Setting limits too low, blocking legitimate large uploads. Always test with real-world payloads.
- Forgetting to apply limits to both request and response. While the attack is usually on request, responses can also be compressed bombs if the upstream is compromised.
- Relying solely on the application layer. The proxy is the first line of defense; do not skip these steps because the app has its own limits.
- Misunderstanding that
client_max_body_sizeapplies to the compressed size. In Nginx, if you enable gunzip, it applies to the decompressed size; otherwise it’s the compressed size. Know which one you are setting. - Not testing with actual attack payloads. A simple curl test may not simulate a real ZIP bomb.
Tips
- Use a dedicated reverse proxy like Nginx or Envoy that has built-in security features, rather than a simple forward proxy.
- Combine limits with a Web Application Firewall (WAF) to detect malicious patterns, but do not rely solely on it.
- Set limits based on your application’s needs. For a file upload service, you may need a larger limit; for an API that accepts JSON, a small limit is fine.
- Document your configuration so future administrators understand why limits are in place.
- Regularly review and update limits as your application evolves.
Troubleshooting
Problem: Legitimate requests are being rejected.
Check the proxy logs for the exact error code. If it’s 413, increase client_max_body_size or LimitRequestBody. If it’s 415, ensure your Content-Encoding regex is not too restrictive.
Problem: The proxy still crashes or runs out of memory.
Your limits may be too high, or the decompression happens before the limit is enforced. Verify that you have disabled request decompression if not needed, and consider using a streaming proxy that can abort mid-decompression.
Problem: The configuration syntax is wrong.
Run a syntax check before reloading. For Nginx, use nginx -t. For HAProxy, use haproxy -c -f /etc/haproxy/haproxy.cfg. For Apache, use apachectl configtest.
Problem: The proxy does not see the Content-Encoding header.
Some clients send the header only when the body is compressed. Ensure your test actually compresses the data using curl --compressed or by setting the header manually.
Frequently Asked Questions
Q: Can a decompression attack happen over HTTPS?
Yes, the attack is independent of encryption. The proxy decompresses after TLS termination, so the same limits apply.
Q: What is a typical safe size limit?
It depends on your use case. For a JSON API, 1MB compressed is generous; for file uploads, you might allow 10MB compressed but limit decompressed to 100MB. Start small and increase as needed.
Q: Does disabling request decompression break legitimate clients?
Only if your clients rely on sending compressed requests. Most clients do not compress request bodies by default, so it’s usually safe to disable.
Q: Should I also limit response decompression?
Yes, if your proxy decompresses responses (e.g., for caching), an upstream could send a bomb. Apply similar limits on the response path.
Q: Can I use a CDN to mitigate this?
Some CDNs have built-in protections, but you should still configure your origin proxy as described.
Q: How do I test if my configuration works?
Create a file that compresses to a small size but decompresses to a huge size (e.g., a 1GB file of zeros compressed with gzip). Send it as a request and verify your proxy rejects it with a 413 or similar.
Related
Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.