Skip to content

Client recv paths lack per-call byte budgets enabling malicious-server DoS #88

Description

@cursor

Summary

Severity: Medium

Location: src/client/mod.rs

Attacker

A malicious or compromised RTMP server (or MITM on RTMPS) that the embedder connects to for play/publish.

Controlled input

Unbounded inbound TCP data during Client::poll() (play loop) and during the AMF command wait in Client::connect() / publish() / play().

Attack path

  1. Victim application calls Client::connect() to an attacker-controlled rtmp:// / rtmps:// URL.
  2. During AMF handshake, wait_for_command() calls recv_message() in a loop (up to 64 iterations) with no total byte budget. Each iteration can reassemble a full RTMP message up to DEFAULT_MAX_MSG_LENGTH (4 MiB), so a server can push ~256 MiB of junk commands before the client gives up.
  3. During playback, Client::poll() reads from the socket in a tight loop until EAGAIN with no per-call byte cap (unlike the server, which uses MAX_RECV_BYTES_PER_CONN_PER_POLL). A fast server can force a single poll() call to drain the kernel recv queue repeatedly (up to the 64 MiB recv_buffer cap), monopolizing the embedder's event-loop thread.

Impact

Thread monopolization and memory pressure in single-threaded embedders; slow or hung connect/play against untrusted servers.

Remediation

Mirror the server fairness caps: bound bytes read per poll() and per command-wait phase (e.g. 256 KiB each), returning ErrorCode::Timeout when the budget is exhausted.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions