Content-Length: 0 as a Body Inspection Bypass
Confirmed once · narrow scope
A Content-Length: 0 header on a request that still
has a body can make a security filter skip inspecting it
completely, while the backend still reads and processes those
bytes as the real request. The payload never gets scanned.
This is different from request smuggling, which needs the front end and back end to disagree about where a message ends, so one request's tail bleeds into the next. This is a single request. The security filter is only deciding whether to inspect based on the declared length, and the backend isn't limiting what it reads to that same length. There's no contamination between requests, just two components trusting different numbers on the same connection. That's probably why this works in cases where 0.CL smuggling doesn't, since it's a lower bar to clear.
This was found while testing one bug bounty target, not in a lab setup, and hasn't been confirmed as a general pattern. It isn't clear exactly what security filter was in front of the target, so this could be specific to that filter or its rules rather than something that holds everywhere. Cloudflare, Akamai, AWS WAF, and other managed WAF products haven't been tested, and there's no claim that they're affected.
POST /login HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 0
username=admin'--&password=x
With the correct Content-Length, this payload normally got
blocked with a 403. Setting Content-Length to zero returned a
200, bypassing the filter. The backend still parsed
username and password out of the bytes
sitting after the headers, even though the declared length was
zero.
The security filter checks the declared Content-Length
to decide whether to bother inspecting a request, instead of
checking what was actually sent. The backend doesn't limit its
read to that same number either. Its code for parsing the body
usually isn't checking Content-Length at all. It just
keeps reading until it has what looks like a full body. Neither
side is doing anything wrong on its own. They just don't agree on
which number actually matters.
How many setups this affects is still unknown. Edge and CDN security filters that rebuild the request before forwarding it are probably less likely to be affected, since they'd be looking at the real bytes instead of trusting the header. Filters that sit inline on a proxy in front of a backend doing raw socket reads seem like a more likely target. That's still just a guess until more stacks get tested.
Backends should limit body reads to the declared
Content-Length instead of reading past it. Security
filters should treat a declared zero length body on a connection
that still has bytes as suspicious instead of trusting the header.