Skip to content

HTTP/2: pending send data OOM/stats/timeout issues

Moderate
mattklein123 published GHSA-8hf8-8gvw-ggvx Jun 30, 2020

Package

No package listed

Affected versions

1.14.2, 1.13.2, 1.12.4 or older

Patched versions

1.14.3, 1.13.3, 1.12.5

Description

Vulnerability type

Uncontrolled Resource Consumption

Attack type

Remote

Impact

Denial-of-service, Resource consumption (memory)

Discoverer(s)/Credits

An OOM issue was initially reported by Bartosz Borkowski (#9891). After investigating the reported issue, Matt Klein discovered the (assumed) root cause.

Description

Envoy employs HTTP/2 stream flow control as configured by the initial_stream_window_size setting that can be configured both on downstream HTTP listeners as well as upstream HTTP clusters. Envoy also limits the number of simultaneous downstream streams as configured by the max_concurrent_streams setting.

Envoy can consume and never release stream memory in the following case:
Untrusted client opens streams up to the max_concurrent_streams limit.
Untrusted client requests a resource that will generate a large response.
Depending on the configuration of initial_stream_window_size for the upstream cluster, Envoy will buffer approximately that amount of memory on behalf of the stream.
If the downstream client does not open receive window, Envoy will start flow control and stop allowing data from upstream.
However, there existed a case in which Envoy would receive the final data of the stream from upstream (pending window), but not have enough open window to send the data to downstream. This data would be buffered forever and not covered by any timeout.

The effectiveness of this attack is limited by both the max_concurrent_streams and initial_stream_window_size settings. However, a malicious client with knowledge of backend configuration may be able to craft a sequence of connections and streams that would cause Envoy to use substantial memory and never free it. (By opening up max_concurrent_streams - 1 streams per connection and using the final stream for normal periodic requests, the connection idle timer would never fire.)

The fix for this CVE is that Envoy will now use the stream_idle_timeout to cover the final data flush in which data may be buffered pending available downstream window. If downstream window is never opened, Envoy will reset the stream and release the buffered data once the idle timeout fires.

Severity

Moderate

CVE ID

CVE-2020-12604

Weaknesses

No CWEs