Hysteria: HTTP Sniff Unbounded Header Read Server DoS
When protocol sniffing is enabled, a Hysteria 2 server will buffer an attacker's HTTP header data indefinitely until the sniff timeout, allowing any authenticated client to exhaust server memory and c
The problem
Hysteria 2's HTTP sniff implementation reads incoming HTTP headers into a growing buffer with no size limit, waiting for a terminal \r\n\r\n sequence before concluding inspection.
An attacker who has valid credentials opens many concurrent TCP streams through the server and sends hundreds of megabytes of HTTP header data per stream, deliberately omitting the final blank line. The server accumulates all of it for the full sniff timeout duration.
With 16 streams each carrying ~800 MB, tested peak memory usage reached 16 GB, triggering an OOM kill.
Proof of concept
# Build and run the published PoC (Go source in the advisory)
# Sends 800 MB of incomplete HTTP headers across 16 streams, holding each open 12 s
./poc_sniff_http_dos \
--server 127.0.0.1:8443 \
--auth sniff-poc-password \
--insecure \
--target-host 192.0.2.1 \
--target-port 80 \
--connections 16 \
--header-bytes 838860800 \
--linger 12
# Core of the generated payload per stream (no trailing \r\n\r\n is intentional):
# GET / HTTP/1.1\r\n
# Host: victim\r\n
# User-Agent: hy2-sniff-poc\r\n
# X-Fill-000000: AAAA...AAA\r\n <- repeated to fill ~800 MB
# <EOF, blank line never sent>The sniff code reads from the client stream byte-by-byte or in small chunks, appending to an in-memory buffer, and only stops when it sees \r\n\r\n or the configured timeout fires. There was no ceiling on how many bytes it would accumulate, so an attacker could pin each goroutine at maximum memory for the entire timeout window.
The patch in 2.9.2 introduces a hard maximum on the number of bytes the HTTP sniffer will buffer before giving up and releasing the data, directly addressing CWE-770 (Allocation of Resources Without Limits or Throttling).
The fix
Upgrade to Hysteria 2 version 2.9.2 or later. The 2.9.2 release adds a byte cap inside the HTTP sniff reader so that oversized or deliberately incomplete headers are rejected early rather than buffered indefinitely. No configuration change is required after upgrading.