influxdata / influxdata/telegraf

Unbounded allocations, parser panics and CPU amplification in multiple input plugins

Open
#19,631 0 comments 0 reactions 0 assignees View on GitHub
bug
Dominant language
Go
Stars
17.8k
Forks
5.8k
Avg merge
1d 20h
Merged PRs (30d)
161

Description

### Relevant code

```text id="7n6j5q"
Multiple Telegraf input plugins contain attacker-controlled allocations, unbounded state retention, or CPU amplification issues that can be triggered by remote network traffic.

1. Riemann listener - Attacker-controlled allocation

File: plugins/inputs/riemann_listener/riemann_listener.go

At line 249, the handler reads a 4-byte uint32 header from the TCP connection representing the message size. At line 257, it allocates a byte slice of exactly that size without applying an upper bound.

This allows a remote sender to request a potentially massive memory allocation because the size specified in the header is not validated before make() is called.

2. sFlow - Attacker-controlled slice pre-allocation and CPU amplification

File: plugins/inputs/sflow/packetdecoder.go

2a. Unbounded sample count allocation (lines 99, 103)

The decoder reads a uint32 sample count from the wire and pre-allocates a slice using that value as its capacity. The value is controlled by the remote sender and is not subject to an upper bound.

2b. Unbounded flow record count (lines 228, 231)

Similarly, decodeFlowRecords reads a uint32 record count from the wire and loops based on that value without applying a reasonable upper bound.

2c. CPU amplification via sampling rate multiplication (line 267)

The frameLength and samplingRate values are both attacker-controlled uint32 values read from the wire. Their product is stored without an overflow check.

Two large uint32 values can cause integer overflow. Additionally, samplingRate is passed through multiple decode functions and can be used to amplify processing work.

3. StatsD - Unbounded per-peer state retention

File: plugins/inputs/statsd/statsd.go

The plugin accumulates per-metric-name state in maps without enforcing a maximum cardinality.

While AllowedPendingMessages limits the input channel depth and MaxTCPConnections limits the number of connections, there is no limit on the number of distinct metric keys that can be retained between gather intervals.

A remote sender can submit metrics with high cardinality, causing these maps to grow until available memory is exhausted.

The maps are replaced during the gather operation, meaning that a burst of unique metric keys between gather intervals cannot be shed before the maps grow.

4. NetFlow - Unbounded per-source template state

File: plugins/inputs/netflow/netflow_decoder.go

4a. Unbounded template map growth (lines 553–554)

The decoder creates a new template system for every unique source IP and stores these systems in an unbounded map.

An attacker capable of spoofing UDP source addresses can cause this map to grow without limit because there is no eviction policy or maximum number of tracked sources.

4b. Unbounded deduplication/logging map (lines 785–787, 819–821, 868–870)

The d.logged map tracks which unknown field types have already been logged, keyed by field type ID.

While this map is bounded in practice under legitimate traffic, crafted packets containing many distinct field type IDs can cause the map to grow without a defined limit.
```

### Logs

```text id="g8q3w2"
None
```

### System info

Latest Telegraf version

### Docker

*No response*

### Steps to reproduce

1. Enable the affected Telegraf input plugin.
2. Send specially crafted network traffic to the corresponding listener.
3. For the Riemann listener, provide a TCP message-size header containing a very large `uint32` value.
4. For sFlow, provide packets containing excessively large sample or flow-record counts and attacker-controlled sampling values.
5. For StatsD, send a sustained stream of metrics with a large number of unique metric names between gather intervals.
6. For NetFlow, send traffic using a large number of distinct spoofed source IP addresses and/or distinct unknown field type IDs.
7. Observe increasing memory consumption and, depending on the affected plugin and payload, excessive CPU consumption or process instability.

### Expected behavior

All attacker-controlled allocation sizes, iteration counts, and retained state should have reasonable upper bounds.

Malformed or excessively large network inputs should be rejected or discarded without causing unbounded memory allocation, state growth, or disproportionate CPU consumption.

### Actual behavior

Several input plugins use attacker-controlled values without sufficient bounds:

* **Riemann:** A remote sender can control the size of a byte-slice allocation through the TCP message-size header.
* **sFlow:** Remote senders can control slice pre-allocation and loop counts through sample and flow-record counts. Attacker-controlled values can also contribute to CPU amplification and integer overflow.
* **StatsD:** An attacker can cause unbounded growth of per-metric state by submitting high-cardinality metric names.
* **NetFlow:** An attacker can cause unbounded growth of per-source template state by spoofing source IP addresses. The logging/deduplication map can also grow through crafted field type IDs.

### Additional info

**Impact:** Remote denial of service through memory exhaustion and/or CPU amplification.

The Riemann listener and sFlow issues can potentially be triggered with a single crafted packet or connection. The StatsD and NetFlow issues require sustained traffic to grow the associated state, but the affected data structures have no inherent maximum size or eviction mechanism.

The issues are particularly relevant for Telegraf instances exposing these input plugins to untrusted or remotely accessible network sources.

Contributor guide

Open the contributing guide

Research direction

Start by reading the handlers and decoders named in plugins/inputs/riemann_listener/riemann_listener.go, plugins/inputs/sflow/packetdecoder.go, plugins/inputs/statsd/statsd.go, and plugins/inputs/netflow/netflow_decoder.go. Trace each attacker-controlled allocation, loop, and retained map, then establish bounded behavior for malformed or excessive network inputs and verify that memory and CPU no longer grow without a limit.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
backend, networking, security
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.