Low and slow: attacks built to stay under the threshold
Low and slow is the class of attacks that succeed by never looking like too much. Slowloris is the best-known member and holds connections open with headers it never finishes; this page covers the family it belongs to, because the same principle produces several techniques, and a defence tuned against one of them frequently misses the others.
Quick facts
- Layer
- Application (7)
- Vector
- Requests delivered or consumed at deliberately minimal rates
- Goal
- Occupy connections, workers, or buffers rather than capacity
- In your logs
- Long-lived connections, few completed requests, low throughput
- Does a WAF stop it?
- Yes, by requiring progress and buffering complete requests, not by limiting rate
The qualifier is the point of the class: every measurement of "too much" is a rate, and these attacks are designed to stay below whatever rate you measure.
The principle they share
Defences against abuse mostly count things per unit of time: requests per second, connections per minute, bytes per interval. Each threshold encodes an assumption that abusive traffic is more traffic.
These techniques invert it. They send less, not more, and occupy a resource by holding it rather than by exhausting it with volume. A threshold set high enough not to inconvenience real users is necessarily far above what these attacks generate, so the counter never trips and the site goes down with the dashboards showing nothing unusual.
Three shapes follow from the principle, distinguished by which part of the exchange is stretched.
Slow headers
The request line arrives, then headers appear one at a time, never reaching the marker that ends them. The connection stays legitimately open because the server cannot know whether the next line is coming.
This is the technique covered in full on Slowloris, including which server architectures reach their ceiling first.
Slow body: the R.U.D.Y. shape
The same principle, applied one stage later.
Where a form or an API accepts a submission, the client announces how much data it intends to send and then sends it at a trickle. The server, having been told a body is coming, waits for it. A submission endpoint that would normally complete in a moment instead holds a worker for as long as the sender chooses.
Two things make this variant awkward. Submission endpoints are usually the expensive ones, so each occupied worker costs more than it would elsewhere. And uploads are legitimately slow, which means the naive fix, refusing requests that take a long time to arrive, breaks the exact feature being abused.
Slow read
The mirror image, and the one most often forgotten.
Here the request completes normally and the response is what stalls: the client accepts data at a minimal rate, so the server holds the response and its buffers while it waits for the recipient to take delivery. From the server's perspective the request was served; from the resource's perspective it is still occupied.
The signal is a set of responses in progress for far longer than the content they carry would explain, with the process itself idle.
Why the usual measures miss it
Three reasons, and they explain why this class survives in environments that are otherwise well defended.
Rate limits do not see it. Nothing exceeds a rate. Counting requests per source produces small numbers, because each source makes few requests and simply never finishes them.
Content rules do not see it. Everything sent is well formed. There is no payload, no anomaly, and nothing a signature could describe.
Monitoring often does not see it. Bandwidth graphs stay flat, processor usage stays low, and error rates rise only at the end when new visitors are refused. The failure appears fully formed rather than as a trend.
Mitigation by layer
Four measures, and they share a shape: require progress rather than enforce speed.
Demand forward progress on incomplete requests. A connection that has not advanced meaningfully is a different thing from a connection that is slow. Where a server can express that distinction, it closes the abusive case and leaves the legitimate one alone.
Bound header time separately from body time. Headers do not legitimately take long. Bodies do, and treating them under one deadline either lets attacks through or breaks uploads.
Buffer complete requests in front of the application. A layer that accepts the whole request before forwarding absorbs slow delivery, which is the same structural defence that answers the header variant.
Cap concurrent incomplete exchanges per source. Both delivery and collection benefit. It misfires on shared addresses, which is the usual trade-off in this category.
What does not help: request rate limits, content rules, and larger servers. The resource being consumed is occupancy, and adding capacity moves the ceiling without changing the mechanism.
Before you set aggressive deadlines
Warning: the reflexive fix is a short absolute time limit on requests, and it removes real users along with the attack.
Slow clients exist and are not doing anything wrong: mobile networks with poor coverage, distant regions, and anyone sending a large file over a constrained link. A deadline treats them as it treats deliberate delay, because from the server's side the two look identical.
The distinction that works is progress, not elapsed time. A client sending steadily but slowly is behaving; a client sending the minimum required to stay connected is not. Where a server or an edge can express that, it should, and where it cannot, header time is the safer thing to constrain, since no genuine client needs minutes to finish sending headers.
Where the platform sits
Bridge WAF sits in front of your origin and accepts complete requests before forwarding them, so slow delivery is absorbed at the edge rather than occupying your application. Rate limiting is applied per domain, which bounds the volume a domain accepts rather than what any single source may hold open. What this does not address is traffic that saturates a link, which is a different layer. See what the platform offers at Bridge CDN.
Questions
What is a low and slow attack?
An attack that occupies connections, workers, or buffers by operating at a minimal rate rather than by generating volume. It succeeds precisely by staying beneath every threshold designed to catch excess, which is why it tends to be diagnosed late.
Why do rate limits not catch it?
Because nothing exceeds a rate at any point. Each source makes very few requests and simply never completes them, so a limit that counts requests per client sees a perfectly unremarkable client, while the resource actually being consumed is counted by nothing at all.
What is the R.U.D.Y. shape?
The slow-body variant. The client announces a submission of a given size and then delivers it at a trickle, holding a worker for as long as it chooses. It targets submission endpoints specifically, which are the expensive ones and often the ones without their own limits.
What is a slow read attack?
The mirror image. The request itself completes normally, and then the client accepts the response so slowly that the server must retain both the response and the buffers holding it. Requiring a complete request achieves nothing against this, because the request was complete.
Does a WAF stop these?
When it buffers complete requests and can require forward progress in both directions, yes. Rules that match on content do not help at all here, since the content is ordinary and the abuse lies entirely in the timing of its delivery.
Will a short request timeout fix it?
It will also disconnect mobile users on poor connections and interrupt legitimate uploads, which is a self-inflicted version of the outage you are preventing. Require forward progress instead, and constrain the time allowed for headers separately from the time allowed for a body.
Progress and buffering rather than rate: the edge accepts a complete request before forwarding it.
off
No request is inspected. Where a slow request is held is a separate property of the edge.
monitor
Matches are recorded on complete requests — which is the stage this class avoids reaching.
block
Refusal applies to complete requests, after the edge has assembled one.
The firewall layer is included with Bridge CDN. Start in monitor: nothing is refused until you decide it should be.
Get started