chunkloris: kestrel (asp.net core 9, h2c)
on this page
part of the chunkloris per-chunk amplification survey. this page is the per-server record for Kestrel (ASP.NET Core 9, h2c) under http/2 (h2c) data frames.
at a glance
- server: Kestrel (ASP.NET Core 9, h2c)
9.0 - runtime: .NET 9
- ecosystem: dotnet
- concurrency model: event-loop
- parser: Kestrel HTTP/2 framer (managed)
- delivery granularity:
per-chunk - chunk-limit helper: none exposed by the framework
- verdict: per-frame β the parser/dispatcher boundary delivers one event per protocol frame (h2 / h3 DATA frame, or ws data frame). cpu cost under paced mode b is measurable per frame.
- scaling exponent (mode a): 0.84 (wall time vs N, log-log slope across common cells)
- scaling exponent (mode b): 1.00
measurements
all cells run on a 1-vcpu docker container. cpu cost is derived from the target containerβs cgroup v2 cpu.stat usage_usec delta around each cell.
| mode | N | wall (s) | server cpu % | Β΅s / frame | basis | ok |
|---|---|---|---|---|---|---|
A-h2-bridge | 50,000 | 0.209 | 37.8 | 1.580 | server-cpu-cgroup | β |
A-h2-bridge | 100,000 | 0.359 | 39.4 | 1.415 | server-cpu-cgroup | β |
A-h2-bridge | 250,000 | 0.810 | 62.6 | 2.031 | server-cpu-cgroup | β |
B-h2-paced-100us | 50,000 | 5.421 | 66.4 | 71.953 | server-cpu-cgroup | β |
B-h2-paced-100us | 100,000 | 10.772 | 55.5 | 59.816 | server-cpu-cgroup | β |
B-h2-paced-100us | 250,000 | 26.967 | 54.3 | 58.560 | server-cpu-cgroup | β |
what this means
the parser/dispatcher path on this server delivers one event per protocol frame (a http/2 (h2c) data frames DATA frame or ws frame), so an attacker who sends a request body as N one-byte frames consumes roughly N Γ (mode-b Β΅s/frame) of server cpu on a single core.
what to do today
- if this is an h2 origin, prefer a frontend that terminates h2 into h1 with
proxy_request_buffering onupstream. - consider imposing a per-stream
DATA-frame credit (count, not bytes) before forwarding the body to the application handler. - HTTP/2 byte-level flow control (
WINDOW_UPDATE) does not bound the number of frames; configure stream-frame-rate limits where the implementation exposes them.
reproducer
the full reproducer for this server is in the paper repo. the docker container pins Kestrel (ASP.NET Core 9, h2c) 9.0 and constrains the test container to a single cpu (--cpus=1). the prober script implements mode a (bridge-coalesced) and mode b (paced 100 Β΅s) per the methodology section.
see the draft pdf for the full per-framework discussion.