Denial Of Service in Aspnet
How Denial Of Service Manifests in ASP.NET
Denial of Service (DoS) in ASP.NET APIs typically exploits resource-intensive operations without proper constraints. Unlike simple flood attacks, application-layer DoS targets specific ASP.NET code paths that can exhaust CPU, memory, or thread pools.
- XML Bomb (Billion Laughs Attack): ASP.NET's legacy
XmlSerializerandDataContractSerializerwill fully expand nested entity references. An attacker sends a small XML payload that expands to gigabytes in memory. Example vulnerable controller:[HttpPost("/process")] public IActionResult ProcessXml([FromBody] string xml) { var serializer = new XmlSerializer(typeof(Config)); using var reader = new StringReader(xml); var config = (Config)serializer.Deserialize(reader); // Vulnerable return Ok(); } - JSON Deserialization Bomb: Using
Newtonsoft.JsonwithTypeNameHandling.Allenables polymorphic deserialization attacks. An attacker can craft JSON that instantiates arbitrary .NET types, leading to CPU/memory exhaustion or even remote code execution if dangerous types are available (CVE-2019-16768). - Regular Expression DoS (ReDoS): ASP.NET model validation often uses complex regexes (e.g., for email validation). A crafted input with catastrophic backtracking can lock a thread. Example:
[RegularExpression(@"^([a-zA-Z0-9])+@([a-zA-Z0-9])+\.([a-zA-Z])+", ErrorMessage = "Invalid email")] public string Email { get; set; } // ReDoS with "aaaaaaaaaaaaaaaaaaaaa@aaaa..." - Unbounded Collections in Query/Form: ASP.NET automatically binds arrays from query strings/form data. An attacker can send thousands of parameters (e.g.,
?id=1&id=2&...), consuming memory and CPU during model binding:[HttpGet("/items")] public IActionResult GetItems([FromQuery] List<int> ids) // No MaxBindingSize { // Processing hundreds of IDs exhausts memory } - File Upload Without Size Limits: ASP.NET Core's default form options allow large file uploads. Without
RequestSizeLimitor IIS request filtering, attackers can upload GBs to fill disk space or memory.
ASP.NET-Specific Detection
Detecting these DoS vectors requires testing the API's response to malicious payloads. middleBrick's black-box scanner probes for unconstrained resource consumption through its Input Validation and Rate Limiting checks.
- XML/JSON Bomb Detection: The scanner sends deeply nested XML/JSON structures (e.g., 100+ levels of expansion) and measures response time/memory indicators (HTTP 500, timeout). A significant slowdown indicates vulnerable deserialization.
- ReDoS Detection: middleBrick submits regex edge-case strings (e.g., repeated characters that cause backtracking) and times the response. If the endpoint takes >5 seconds with a 50-character input, it flags a potential ReDoS.
- Collection Binding Overflow: The scanner sends thousands of query parameters (e.g.,
?param=1repeated 10,000 times) and checks for HTTP 507 (Insufficient Storage) or prolonged processing. - File Upload Size: middleBrick attempts to upload a file exceeding 100MB and observes if the API rejects it with 413 (Payload Too Large) or accepts it.
- Rate Limiting Absence: The scanner performs rapid sequential requests (10 in 2 seconds). If all succeed without 429 responses, it flags missing rate limiting.
With middleBrick, you can scan any ASP.NET Web API endpoint without credentials. For example, using the CLI:
middlebrick scan https://api.example.com/process-xmlThe report will show a per-category breakdown. If DoS issues exist, the Input Validation or Rate Limiting category will score low (e.g., C–F), with findings like "XML entity expansion not restricted" or "No limit on query parameter count."ASP.NET-Specific Remediation
Fixing DoS vulnerabilities in ASP.NET involves leveraging built-in constraints and safe defaults. Below are code-level fixes for each pattern.
- Secure XML Processing: Use
XmlReaderwith strict settings to prevent entity expansion:[HttpPost("/process")] public IActionResult ProcessXml([FromBody] string xml) { var settings = new XmlReaderSettings { DtdProcessing = DtdProcessing.Prohibit, MaxCharactersFromEntities = 1024, // Limit entity expansion MaxCharactersInDocument = 1024 * 1024 // 1MB max }; using var reader = XmlReader.Create(new StringReader(xml), settings); var serializer = new XmlSerializer(typeof(Config)); var config = (Config)serializer.Deserialize(reader); return Ok(); } - Safe JSON Deserialization: Disable polymorphic type handling and set size limits:
services.AddControllers() .AddJsonOptions(options => { options.JsonSerializerOptions.TypeNameHandling = JsonTypeNameHandling.None; options.JsonSerializerOptions.MaxDepth = 64; // Prevent deep nesting }); - Regex Timeouts: Use
Regexwith a timeout in validation attributes. Create a custom attribute:public class SafeRegexAttribute : RegularExpressionAttribute { public SafeRegexAttribute(string pattern) : base(pattern) { } protected override ValidationResult IsValid(object value, ValidationContext context) { try { var regex = new Regex(Pattern, RegexOptions.Compiled, TimeSpan.FromSeconds(2)); return regex.IsMatch(value?.ToString() ?? "") ? ValidationResult.Success : new ValidationResult(ErrorMessage); } catch (RegexMatchTimeoutException) { return new ValidationResult("Validation timeout - potential ReDoS"); } } } - Limit Collection Binding: Use
[FromQuery]with a custom model binder that caps collection size, or validate count:[HttpGet("/items")] public IActionResult GetItems([FromQuery] List<int> ids) { if (ids?.Count > 100) return BadRequest("Too many IDs. Max 100 allowed."); // ... } - Request Size Limits: Apply globally or per-endpoint:
[HttpPost("/upload")] [RequestSizeLimit(10_000_000)] // 10MB max public async Task<IActionResult> Upload(IFormFile file) { if (file.Length > 10_000_000) return BadRequest("File too large"); // ... } - Rate Limiting Middleware: Use ASP.NET Core's built-in rate limiter (available in .NET 7+):
builder.Services.AddRateLimiter(options => { options.GlobalLimiter = PartitionedRateLimiter.Create<HttpContext, string>(httpContext => RateLimitPartition.GetFixedWindowLimiter( partitionKey: httpContext.User.Identity?.Name ?? httpContext.Request.Headers.Host.ToString(), factory: partition => new FixedWindowRateLimiterOptions { AutoReplenishment = true, PermitLimit = 100, // 100 requests QueueLimit = 0, Window = TimeSpan.FromMinutes(1) })); }); app.UseRateLimiter();
After applying these fixes, rescan with middleBrick to verify the Input Validation and Rate Limiting scores improve. The remediation guidance in middleBrick's report will reference OWASP API4:2023 (Unrestricted Resource Consumption) and provide ASP.NET-specific code samples like those above.
Related CWEs: resourceConsumption
| CWE ID | Name | Severity |
|---|---|---|
| CWE-400 | Uncontrolled Resource Consumption | HIGH |
| CWE-770 | Allocation of Resources Without Limits | MEDIUM |
| CWE-799 | Improper Control of Interaction Frequency | MEDIUM |
| CWE-835 | Infinite Loop | HIGH |
| CWE-1050 | Excessive Platform Resource Consumption | MEDIUM |