How to Test for TLS Compression Vulnerabilities (CRIME & BREACH) with testssl.sh

Use ./testssl.sh --crime to detect TLS-level compression (CRIME) and ./testssl.sh --breach to detect HTTP-level compression (BREACH) on any target host.

Testing for TLS compression vulnerabilities is a critical step in securing web servers against information leakage attacks. The drwetter/testssl.sh repository provides specialized command-line flags to detect both CRIME and BREACH vulnerabilities through automated TLS handshake analysis and HTTP header inspection. This guide explains how to use testssl.sh to identify these compression-related security flaws.

Understanding TLS Compression Attacks

Before running the tests, it is important to distinguish between the two compression vulnerabilities that testssl.sh detects.

What is CRIME?

CRIME (Compression Ratio Info-leak Made Easy) exploits TLS-level compression (typically zlib) supported in TLS 1.2 and earlier. When a server accepts compressed TLS records, an attacker can inject chosen plaintext into a victim's requests and observe the compressed response size to recover session cookies or tokens.

What is BREACH?

BREACH (Browser Reconnaissance and Exfiltration via Adaptive Compression of Hypertext) targets HTTP-level compression (gzip, deflate, or brotli) rather than TLS compression. Even when TLS compression is disabled, HTTP compression of response bodies can leak secrets through similar side-channel techniques if the response contains both attacker-controlled input and secret tokens.

Testing for CRIME with testssl.sh

The test_crime function in testssl.sh (lines 18184–18242) implements the CRIME detection logic by manipulating the TLS handshake to force a compression method disclosure.

How the CRIME Test Works

According to the source code in drwetter/testssl.sh, the script performs the following steps:

  1. Disables client compression advertisement: The script sets offer_compression=false in the ClientHello, explicitly telling the server that the client does not support TLS compression.
  2. Inspects the ServerHello: After the handshake, the script extracts the tls_compression_method field from the ServerHello response.
  3. Evaluates vulnerability: If the server selects any compression method other than null (0x00), the test reports Vulnerable to CRIME and caps the overall grade at C.

Running the CRIME Test

Execute the following command to check for TLS compression vulnerabilities:

./testssl.sh --crime example.com:443

For mail servers using IMAPS or other TLS-wrapped protocols:

./testssl.sh --crime imap.example.org:993

The console output will display:


CRIME, TLS (Vulnerable to CRIME)

If vulnerable, or:


CRIME, TLS (Not vulnerable)

If the server correctly rejects compression.

Testing for BREACH with testssl.sh

The test_breach function (lines 18318–18344) in testssl.sh detects HTTP-level compression by analyzing response headers rather than TLS handshake parameters.

How the BREACH Test Works

The BREACH detection logic in drwetter/testssl.sh operates as follows:

  1. Sends compression-capable request: The script transmits an HTTP GET request including an Accept-Encoding header listing all common compression algorithms: gzip, deflate, compress, and br (brotli).
  2. Analyzes response headers: The script inspects the HTTP response for a Content-Encoding header.
  3. Determines vulnerability: If the server returns any compression encoding, the test flags Vulnerable to BREACH; otherwise, it reports No HTTP compression (OK).

Running the BREACH Test

To check for HTTP compression vulnerabilities:

./testssl.sh --breach https://example.com/

You can combine both compression tests in a single invocation:

./testssl.sh --crime --breach example.com:443

The output will indicate:


BREACH (gzip HTTP compression)

Or if safe:


BREACH (no gzip/deflate/compress/br HTTP compression (OK))

Interpreting JSON Output

When using the --json or --jsonfile options, testssl.sh exports structured results with specific identifiers:

{
  "CRIME_TLS": {
    "severity": "CRITICAL",
    "description": "Vulnerable to CRIME"
  },
  "BREACH": {
    "severity": "CRITICAL",
    "description": "gzip HTTP compression"
  }
}

These jsonID values allow automated security scanners to parse compression vulnerability status without parsing human-readable text.

Summary

  • CRIME attacks TLS-level compression (zlib), while BREACH exploits HTTP-level compression (gzip/deflate/br).
  • Use ./testssl.sh --crime to detect TLS compression by analyzing the ServerHello response for non-null compression methods (source: testssl.sh lines 18184–18242).
  • Use ./testssl.sh --breach to detect HTTP compression by checking for Content-Encoding headers in HTTP responses (source: testssl.sh lines 18318–18344).
  • Both tests set severity to CRITICAL in JSON output when vulnerabilities are detected, with CRIME additionally capping the overall grade at C.

Frequently Asked Questions

What is the difference between CRIME and BREACH?

CRIME targets compression at the TLS protocol level (specifically the DEFLATE algorithm used in TLS compression), allowing attackers to recover session cookies by observing the size of compressed TLS records. BREACH targets compression at the HTTP application level (gzip, deflate, or brotli), exploiting the fact that HTTP responses often contain both attacker-controlled input and secret tokens. While CRIME requires TLS compression to be enabled, BREACH can affect any HTTPS site that compresses HTTP responses regardless of TLS settings.

Does testssl.sh require root privileges to test for compression vulnerabilities?

No, testing for CRIME and BREACH with testssl.sh does not require root privileges. The script operates as a standard TLS client using OpenSSL's s_client command for the CRIME test and standard HTTP GET requests for the BREACH test. However, if you are scanning ports below 1024 on the local machine or need to bind to specific local ports, elevated privileges might be necessary, but this is not specific to compression testing.

How does testssl.sh detect CRIME without offering compression?

The test_crime function in testssl.sh (lines 18184–18242) deliberately sets offer_compression=false in the ClientHello to signal that the client does not support TLS compression. According to the TLS specification, if the server respects this and only supports compression, it should either select null compression (0x00) or abort the handshake. The script then inspects the ServerHello response; if the server selects any non-null compression method despite the client's refusal, testssl.sh reports the server as vulnerable to CRIME.

Can BREACH be mitigated while keeping HTTP compression enabled?

Mitigating BREACH while maintaining HTTP compression is challenging because the vulnerability fundamentally relies on the side-channel created by compression. According to the drwetter/testssl.sh source code documentation and security best practices, effective mitigations include implementing CSRF tokens that change per request (breaking the attack's ability to guess secrets across multiple requests), separating secrets from attacker-controlled input in the response body, or using length-hiding techniques. However, the only definitive fix is disabling HTTP compression entirely, which testssl.sh identifies when the server returns no Content-Encoding header in response to the BREACH test probe.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →