Heap Overflow in Aspnet
How Heap Overflow Manifests in Aspnet
In ASP.NET applications, heap overflows usually appear when developers drop down to unsafe code or misuse interop APIs that allocate unmanaged memory on the heap. A common pattern is using Marshal.AllocHGlobal to reserve a buffer based on user‑supplied length, then copying data without validating that the length matches the actual payload size.
// Vulnerable: length taken directly from request query
public IActionResult Upload([FromQuery] int size)
{
IntPtr ptr = Marshal.AllocHGlobal(size); // heap allocation
// Assume the request body contains exactly 'size' bytes
Request.Body.ReadAsync(new Span(ptr.ToPointer(), size)).Wait();
// …process data…
Marshal.FreeHGlobal(ptr);
return Ok();
}
If an attacker supplies a larger size than the actual request body, the read will overrun the allocated heap block, corrupting adjacent heap metadata or other objects. Similar issues arise when:
- Using
fixedbuffers inside unsafe structs and copying data withBuffer.BlockCopywithout length checks. - Calling native libraries via P/Invoke that expect a pre‑allocated buffer; the managed side miscalculates the required size.
- Deserializing untrusted data with custom
System.Text.Jsonconverters that allocate buffers based on fields in the payload.
These code paths are frequently found in middleware that handles file uploads, custom formatters, or performance‑optimized serialization routines. The overflow may not crash the process immediately; instead, it can lead to arbitrary code execution when the heap manager’s internal structures are overwritten—a classic exploitation technique seen in CVEs such as CVE‑2020-0609 (ASP.NET Core remote code execution via heap corruption).
Aspnet-Specific Detection
Because middleBrick performs unauthenticated, black‑box scanning, it looks for observable symptoms of heap corruption rather than probing internal memory directly. When an ASP.NET endpoint mishandles input size, the scanner may notice:
- HTTP 500 responses containing
AccessViolationExceptionorStackOverflowExceptionstack traces in error pages (when detailed errors are enabled). - Abnormally large response bodies or delayed responses that indicate the process is struggling with heap corruption.
- Changes in response timing when fuzzing length parameters (e.g., query string
sizeor form fieldlength)—a classic sign of a buffer‑length‑dependent code path.
During the Input Validation check, middleBrick sends a series of progressively larger payloads to parameters that influence buffer allocation (identified via OpenAPI spec analysis or heuristic URL‑parameter inspection). If the response shifts from successful (200) to error (500) or the connection drops, the finding is flagged as a potential heap‑overflow risk with severity high and includes the exact parameter and payload size that triggered the anomaly.
Example CLI usage:
middlebrick scan https://api.example.com/upload --parameter size --min 100 --max 5000 --step 500
The command tells middleBrick to test the size query parameter with incremental values, producing a JSON report that highlights any step where the status code changes or an error message appears.
Aspnet-Specific Remediation
The safest approach is to avoid unmanaged heap allocation altogether and rely on ASP.NET’s built‑in, managed buffers. When interop is unavoidable, validate every size against the actual data length before copying.
// Safe: validate length against the actual request body length
public IActionResult Upload([FromQuery] int size)
{
if (size < 0 || size > 10_000) // reasonable upper bound
return BadRequest("Invalid size");
// Read the body into a managed buffer first
var body = new byte[size];
int read = await Request.Body.ReadAsync(body.AsMemory(0, size));
if (read != size)
return BadRequest("Payload length does not match declared size");
// Now you can safely pass the managed buffer to native code if needed
fixed (byte* p = body)
{
NativeMethod(p, (uint)size);
}
return Ok();
}
Additional ASP.NET‑specific mitigations:
- Enable request size limits in
Startup.csorProgram.cs:builder.Services.Configure<FormOptions>(o => o.MultipartBodyLengthLimit = 10_000); // 10 KB - Prefer
System.Buffers.ArrayPool<byte>for temporary buffers and always return them to the pool. - When using
Span<T>, allocate withstackalloconly for sizes known at compile time and verified to be small (typically < 512 bytes). - Turn off detailed error messages in production (
UseDeveloperExceptionPageonly in Development) to avoid leaking stack traces that could aid heap‑overflow exploitation. - Regularly update the ASP.NET runtime and any native dependencies; many heap‑overflow bugs are patched in newer releases (e.g., .NET 6.0.13 addressed CVE‑2022-23295 in the HTTP.sys driver).
By combining input validation, safe buffer handling, and ASP.NET’s request‑size controls, you eliminate the conditions that allow a heap overflow to be triggered from unauthenticated input.