Full Disclosure mailing list archives
WatsonWebserver v7.1.0 HTTP/1 Chunked Request Processing Bypasses MaxRequestBodySize
From: Ron E <ronaldjedgerson () gmail com>
Date: Sat, 22 Aug 2026 08:43:02 -0400
WatsonWebserver contains an HTTP/1 request body size-limit bypass when
processing requests using Transfer-Encoding: chunked.
The framework's configured Settings.IO.MaxRequestBodySize limit is enforced
when a request declares its body size using Content-Length. However,
requests using chunked transfer encoding are processed through a separate
body-reading path that accumulates decoded chunks into a MemoryStream
without enforcing the same cumulative request-body limit.
As a result, a remote client can submit an HTTP/1 request whose decoded
body exceeds the administrator-configured MaxRequestBodySize by using
chunked transfer encoding instead of Content-Length.
A proof of concept configured:
MaxRequestBodySize = 16 bytes
and submitted a chunked request containing:
24 bytes
of decoded body data.
WatsonWebserver accepted the complete request, delivered all 24 bytes to
the application, and returned:
HTTP/1.1 200 OK
len=24
This confirms that MaxRequestBodySize is not consistently enforced across
supported HTTP/1 request-framing mechanisms.
Because the chunked body is accumulated in memory without a cumulative
MaxRequestBodySize check, an attacker may also be able to cause excessive
memory and CPU consumption by submitting substantially larger request
bodies. The supplied PoC directly demonstrates the size-limit bypass;
denial of service is a potential consequence rather than a demonstrated
result of the 24-byte test.
Vulnerability Description
WatsonWebserver provides the following configuration setting for
restricting HTTP request body size:
Settings.IO.MaxRequestBodySize
For HTTP/1 requests containing a Content-Length header, WatsonWebserver
parses the declared body size and rejects the request when it exceeds the
configured maximum.
However, HTTP/1 also permits request bodies to be framed using:
Transfer-Encoding: chunked
Chunked requests do not contain a single up-front Content-Length. Instead,
the body is transmitted as a sequence of independently sized chunks.
WatsonWebserver handles these requests through ReadChunkedBodyAsync(),
which repeatedly reads chunks and writes their contents into an in-memory
MemoryStream.
The implementation does not maintain a cumulative decoded-body length and
does not compare the accumulated size against Settings.IO.MaxRequestBodySize
.
Consequently, a client can bypass the configured request body limit simply
by changing the HTTP framing mechanism from Content-Length to
Transfer-Encoding:
chunked.
Technical AnalysisContent-Length Path
When WatsonWebserver encounters a request containing Content-Length, the
parsed length is stored in:
metadata.ContentLength = parsedContentLength;
The framework subsequently enforces MaxRequestBodySize:
if (settings.IO.MaxRequestBodySize > 0 &&
metadata.ContentLength > settings.IO.MaxRequestBodySize)
{
throw new IOException(
"Request body size "
+ metadata.ContentLength
+ " exceeds maximum allowed size "
+ settings.IO.MaxRequestBodySize
+ ".");
}
The configured maximum is therefore enforced for requests whose body
length is known through Content-Length.
Chunked Request Path
Requests using:
Transfer-Encoding: chunked
follow a different body-processing path.
The relevant implementation is:
private async Task<byte[]> ReadChunkedBodyAsync(
CancellationToken token)
{
using (MemoryStream memoryStream = new MemoryStream())
{
while (true)
{
Chunk chunk =
await ReadChunk(token)
.ConfigureAwait(false);
if (chunk.Data != null &&
chunk.Data.Length > 0)
{
memoryStream.Write(
chunk.Data,
0,
chunk.Data.Length);
}
if (chunk.IsFinal)
break;
}
_BodyComplete = true;
return memoryStream.ToArray();
}
}
Each decoded chunk is appended directly to the MemoryStream:
memoryStream.Write(
chunk.Data,
0,
chunk.Data.Length);
There is no equivalent check against:
Settings.IO.MaxRequestBodySize
before the write.
The loop continues until the terminating chunk is received.
Proof of ConceptServer Configuration
The proof of concept configures WatsonWebserver with:
server.Settings.IO.MaxRequestBodySize = 16;
The maximum accepted request body should therefore be:
16 bytes
Malicious Request
The client submits a valid chunked HTTP/1 request:
POST / HTTP/1.1
Host: 127.0.0.1
Transfer-Encoding: chunked
Connection: close
8
abcdefgh
8
ijklmnop
8
qrstuvwx
0
The request contains three chunks.
Each chunk contains:
8 bytes
giving a cumulative decoded request body of:
8 + 8 + 8 = 24 bytes
The body therefore exceeds the configured limit by:
24 - 16 = 8 bytes
or:
150% of the configured maximum.
Observed HTTP Response
WatsonWebserver accepts the request and returns:
HTTP/1.1 200 OK Content-Type: text/plain Content-Length: 6 Date: Thu, 06
Aug 2026 01:16:34 GMT Connection: close Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: OPTIONS, HEAD, GET, PUT, POST, DELETE, PATCH
Access-Control-Allow-Headers: * Access-Control-Expose-Headers: Accept: */*
Accept-Language: en-US, en Accept-Charset: ISO-8859-1, utf-8 Cache-Control:
no-cache Host: 127.0.0.1:44009 len=24
The application reports:
len=24
confirming that the complete decoded body reached the application despite:
MaxRequestBodySize = 16
Security ImpactConfirmed Impact
The PoC directly demonstrates that a remote HTTP client can bypass the
configured:
Settings.IO.MaxRequestBodySize
restriction when using chunked transfer encoding.
The confirmed impact is therefore:
- bypass of the configured HTTP request-body size restriction;
- acceptance of request bodies larger than the administrator-defined
maximum; and
- in-memory processing of data that should have been rejected by the
configured limit.
Resource Consumption
The affected chunked path accumulates the decoded body in a MemoryStream:
memoryStream.Write(
chunk.Data,
0,
chunk.Data.Length);
and ultimately performs:
return memoryStream.ToArray();
Because there is no cumulative MaxRequestBodySize check in this path,
substantially larger request bodies can potentially consume increasing
amounts of process memory and processing time.
Depending on deployment configuration, available resources, concurrency,
reverse proxies, transport timeouts, and application-specific controls,
this may contribute to:
- excessive memory consumption;
- increased CPU utilization;
- request-processing degradation; and
- denial of service.
The supplied 24-byte PoC demonstrates the *security-control bypass*, not
resource exhaustion itself.
Ron Edgerson
Vulnerability Researcher & Exploit Developer
CVE Research | Binary Exploitation | Application & Systems Security
Responsible Disclosure • Proof-of-Concept Development
🌐 https://github.com/ob1sec
🔗 https://www.linkedin.com/in/ronedgerson1
<https://linkedin.com/in/yourhandle>
_______________________________________________
Sent through the Full Disclosure mailing list
https://nmap.org/mailman/listinfo/fulldisclosure
Web Archives & RSS: https://seclists.org/fulldisclosure/
Current thread:
- WatsonWebserver v7.1.0 HTTP/1 Chunked Request Processing Bypasses MaxRequestBodySize Ron E (Aug 26)
