Skip to main content

Asymmetric denial of service - Content length

Need

Validation and enforcement of Content-Length field in requests

Context

  • Usage of C# 7.1 for developing applications with advanced language features and improvements
  • Usage of Microsoft.AspNetCore.Mvc for building web applications with ASP.NET Core MVC

Description

Non compliant code

[HttpPost]
public async Task<IActionResult> Post([FromBody] string data)
{
// Process the data
return Ok();
}

In the above code, the HTTP POST method accepts any amount of data from the client without any restrictions. The [FromBody] attribute tells the framework to get the data from the body of the HTTP request.

When a client sends a request to this endpoint with a very large Content-Length header, the server will start reading the data and continue to do so until it has read the amount of data specified in the Content-Length header.

While the server is waiting for the data to arrive, it keeps the connection open. This can be exploited by an attacker who sends a large Content-Length header, but only a small amount of data. The server will keep the connection open, waiting for the rest of the data to arrive, which it never does. This can lead to a Denial of Service (DoS) attack, as it can consume server resources and potentially block other legitimate requests.

Steps

  • Implement input validation to ensure that the Content-Length field is within an acceptable range.
  • Set a maximum limit for the Content-Length field to prevent excessively large values.
  • Implement rate limiting or request throttling mechanisms to prevent an attacker from sending a large number of requests with high Content-Length values.
  • Implement timeout mechanisms to terminate idle connections after a certain period of inactivity.
  • Consider implementing request size limits to prevent excessively large requests from consuming server resources.
  • Regularly update and patch the server software to ensure that any known vulnerabilities related to Content-Length handling are addressed.

Compliant code

[HttpPost]
[RequestSizeLimit(1000000)] // Limit the request size to 1MB
public async Task<IActionResult> Post()
{
long? contentLength = HttpContext.Request.ContentLength;
if (contentLength > 1000000) // Check if the Content-Length is more than 1MB
{
return BadRequest("Content-Length is too large.");
}

using (StreamReader reader = new StreamReader(Request.Body, Encoding.UTF8))
{
string data = await reader.ReadToEndAsync();
// Process the data
}

return Ok();
}

The updated code includes several measures to mitigate the risk of an asymmetric denial of service attack via the Content-Length field.

Firstly, the [RequestSizeLimit(1000000)] attribute is added to the Post method. This attribute sets a maximum limit for the size of the request body to 1MB. This prevents an attacker from sending a request with an excessively large body.

Next, the Content-Length of the request is retrieved and checked. If the Content-Length is more than 1MB, the method returns a BadRequest response. This is an example of input validation, which ensures that the Content-Length field is within an acceptable range.

The StreamReader is used to read the request body. This is done within a using statement to ensure that the StreamReader is properly disposed of after use, which helps to prevent resource leaks.

Finally, the method returns an Ok response if the request is processed successfully.

In addition to these code changes, it's also recommended to implement rate limiting or request throttling mechanisms to prevent an attacker from sending a large number of requests with high Content-Length values. Timeout mechanisms should also be implemented to terminate idle connections after a certain period of inactivity. Regularly updating and patching the server software is also important to ensure that any known vulnerabilities related to Content-Length handling are addressed.

References