Skip to content

Missing ReadHeaderTimeout/ReadTimeout/WriteTimeout in API HTTP server causes DoS via slowloris/slow-read #1888

@neekolas

Description

@neekolas

Severity: High | Likelihood: High | Impact: Medium | Type: Vulnerability

Details

The API server starts an http.Server with only IdleTimeout configured, omitting ReadHeaderTimeout, ReadTimeout, and WriteTimeout. This allows attackers to exhaust resources by slowly sending headers/bodies or by not reading server-streamed responses, resulting in denial of service.

When the API is enabled, the node binds to : and serves HTTP/1.1 and h2c (HTTP/2 cleartext). The http.Server is configured with only IdleTimeout and no ReadHeaderTimeout, ReadTimeout, or WriteTimeout, while the http2.Server also lacks read-idle bounds. As a result, an attacker can hold connections by trickling request headers (HTTP/1.1) or HTTP/2 frames, or by opening server-streaming RPCs (SubscribeEnvelopes) and not reading responses, causing stream.Send to block indefinitely. Interceptors run only after request parsing, so they do not mitigate slow header/body attacks. This enables low-cost resource exhaustion and denial of service of the node's replication/metadata APIs and publishing endpoint.

Exploitation

Scenario 1

HTTP/1.1 slowloris: an attacker opens many TCP connections to the API port and slowly sends request headers without completing them; without ReadHeaderTimeout, the server waits indefinitely per connection, consuming goroutines and causing DoS.

Preconditions / Assumptions:

  • (a) API is enabled and listening on a reachable TCP port
  • (b) http.Server lacks ReadHeaderTimeout/ReadTimeout/WriteTimeout (only IdleTimeout set)
  • (c) No mandatory reverse proxy/LB enforcing header/body timeouts in front of the server
  • (d) Attacker can open many concurrent connections to the API port

Scenario 2

Slow-read on server-streaming SubscribeEnvelopes: an attacker starts many SubscribeEnvelopes streams and then stops reading; without WriteTimeout, periodic keepalive/payload writes block indefinitely, tying up handler goroutines and degrading availability.

Preconditions / Assumptions:

  • (a) API is enabled and replication SubscribeEnvelopes handler is active
  • (b) http.Server lacks WriteTimeout
  • (c) SubscribeEnvelopes sends initial and periodic keepalives/payloads
  • (d) Attacker can establish many streams and stop reading from the socket

Scenario 3

HTTP/2 h2c amplification: an attacker uses h2c to slowly deliver headers/frames and/or creates many server-streaming RPCs per connection while slow-reading; without HTTP/2 read-idle bounds and write timeouts, multiple blocked streams exhaust resources and deny service.

Preconditions / Assumptions:

  • (a) API is enabled with h2c (HTTP/2 cleartext) support
  • (b) http2.Server has only IdleTimeout; no read-idle timeout configured
  • (c) http.Server lacks WriteTimeout
  • (d) Attacker can open HTTP/2 connections, create multiple streams, and slow-read or trickle headers

Files impacted

  • pkg/api/server.go

Lines 104-113:

h2cHandler := h2c.NewHandler(mux, &http2.Server{
    IdleTimeout: 5 * time.Minute,
})
// TODO: Do we need more timeouts?
svc.httpServer = &http.Server{
    Handler:     handleCORS(h2cHandler),
    IdleTimeout: 5 * time.Minute,
}

Metadata

Metadata

Labels

Type

No type

Projects

Status

No status

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions