Regex Dos in Aspnet with Basic Auth
Regex Dos in Aspnet with Basic Auth — how this specific combination creates or exposes the vulnerability
In ASP.NET applications, using regular expressions to validate or parse credentials transmitted via HTTP Basic Authentication can introduce a Regex Denial-of-Service (ReDoS) vulnerability. Basic Auth encodes a username and password in a Base64 string inside the Authorization header, but server-side code often decodes this value and applies regex checks for format, length, or allowed character sets.
When those regex patterns are poorly constructed—using nested quantifiers, overlapping repetitions, or ambiguous character classes—they become susceptible to exponential backtracking when presented with specially crafted input. Because Basic Auth credentials are supplied on every request, an attacker can send a long, complex header value designed to trigger catastrophic backtracking, consuming significant CPU time within the ASP.NET pipeline.
For example, a developer might enforce a password policy with a pattern such as ^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,64}$ applied to the decoded password portion. While this regex appears safe, subtle interactions between lookaheads and quantifiers can still cause pathological performance on certain inputs. Additionally, regexes applied to the username part or to the entire header value compound the risk.
This becomes a concern in scenarios where the application parses the Authorization header manually, perhaps to extract or validate claims before issuing a token. If the regex engine processes malicious input in a tight loop for each request, the server can experience high CPU utilization, effectively creating a denial-of-service condition without requiring authentication to succeed.
ASP.NET’s built-in mechanisms for Basic Auth typically do not use vulnerable patterns, but custom middleware or filters that parse and validate credentials remain at risk. The combination of per-request authentication data and complex regex logic is what makes this vector notable.
Basic Auth-Specific Remediation in Aspnet — concrete code fixes
To mitigate Regex Dos risks in ASP.NET when using Basic Authentication, avoid using regular expressions to validate credentials whenever possible. Instead, rely on straightforward string operations and built-in framework features. When regex is necessary, prefer simple, linear patterns and leverage tools to verify acyclicity.
Below are concrete remediation steps and code examples for ASP.NET Core applications.
1. Avoid regex for credential validation
Validate length and allowed character sets using simple logic rather than complex patterns. For example, to check a password policy, use character iteration or predefined character classes without backtracking-heavy quantifiers.
// ✅ Recommended: simple validation without regex
bool IsValidPassword(string password)
{
if (password is null || password.Length < 8 || password.Length > 64)
return false;
bool hasUpper = false, hasLower = false, hasDigit = false;
foreach (char c in password)
{
if (char.IsUpper(c)) hasUpper = true;
else if (char.IsLower(c)) hasLower = true;
else if (char.IsDigit(c)) hasDigit = true;
}
return hasUpper && hasLower && hasDigit;
}
2. Use framework-native Basic Auth parsing
Prefer ASP.NET Core’s built-in mechanisms or standard libraries to decode and parse credentials. This reduces custom parsing logic and associated regex misuse.
// ✅ Using System.Net to parse Basic Auth header
public (string username, string password) ParseBasicAuthHeader(string authHeader)
{
if (string.IsNullOrWhiteSpace(authHeader) || !authHeader.StartsWith("Basic ", StringComparison.OrdinalIgnoreCase))
throw new UnauthorizedAccessException("Invalid Authorization header");
var base64 = authHeader.Substring("Basic ".Length).Trim();
var credentialBytes = Convert.FromBase64String(base64);
var credentials = Encoding.UTF8.GetString(credentialBytes).Split(':', 2);
if (credentials.Length != 2)
throw new UnauthorizedAccessException("Invalid credentials format");
return (credentials[0], credentials[1]);
}
3. If regex is required, keep it simple and test for ReDoS
Limit quantifiers, avoid nested groups, and ensure patterns are anchored with clear boundaries. Use static analysis tools to detect problematic patterns before deployment.
// ✅ Safer regex example with no nested quantifiers
// This pattern checks for at least one uppercase, one lowercase, and one digit
// without complex overlapping lookaheads
Regex simplePolicy = new Regex(@"^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)[A-Za-z\d]{8,64}$");
bool matches = simplePolicy.IsTest(password);
4. Apply middleware early to reject malformed headers
Add a lightweight middleware that inspects the Authorization header format and rejects obviously malformed values before they reach authentication logic that might use regex.
// ✅ Middleware to reject suspiciously long or malformed Basic Auth headers
app.Use(async (context, next) =>
{
if (context.Request.Headers.TryGetValue("Authorization", out var authValues))
{
var auth = authValues.ToString();
if (auth.StartsWith("Basic ", StringComparison.OrdinalIgnoreCase))
{
var payload = auth.Substring(6).Trim();
if (payload.Length > 500) // reject overly long headers
{
context.Response.StatusCode = 400;
return;
}
}
}
await next();
});
These practices reduce the attack surface for Regex Dos in ASP.NET applications that rely on Basic Authentication while maintaining clarity and performance.
Related CWEs: inputValidation
| CWE ID | Name | Severity |
|---|---|---|
| CWE-20 | Improper Input Validation | HIGH |
| CWE-22 | Path Traversal | HIGH |
| CWE-74 | Injection | CRITICAL |
| CWE-77 | Command Injection | CRITICAL |
| CWE-78 | OS Command Injection | CRITICAL |
| CWE-79 | Cross-site Scripting (XSS) | HIGH |
| CWE-89 | SQL Injection | CRITICAL |
| CWE-90 | LDAP Injection | HIGH |
| CWE-91 | XML Injection | HIGH |
| CWE-94 | Code Injection | CRITICAL |