← all writeups

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.