Regex Dos in Aspnet with Mutual Tls
Regex Dos in Aspnet with Mutual Tls — how this specific combination creates or exposes the vulnerability
Regex Denial-of-Service (ReDoS) occurs when a regular expression has overlapping or nested quantifiers on unbounded input, causing catastrophic backtracking. In ASP.NET applications, this typically surfaces in request validation, route matching, or custom header parsing. When Mutual TLS (mTLS) is enforced, the server requires a client certificate during the TLS handshake, establishing a strong identity binding before the application layer processes requests. This shifts the attack surface: the mTLS layer guarantees the client is authenticated with a valid certificate, which may lead developers to assume the request is inherently safe and to apply less scrutiny or more permissive parsing rules.
The combination of mTLS and regex-heavy processing can expose subtle issues. For example, an endpoint that inspects the Subject Alternative Name (SAN) field in the client certificate using a complex regex may inadvertently introduce a ReDoS pattern. Because mTLS provides transport-level assurance, developers might skip additional validation layers or logging that would otherwise detect abuse, focusing instead on business logic. Attackers can still exploit regex paths if the certificate contains crafted fields (e.g., a long string in the Common Name or SAN) that match a vulnerable pattern. Moreover, if the application uses regex to correlate certificate thumbprints or to map certificate attributes to roles, inefficient patterns can degrade performance under crafted inputs, even when the TLS channel is trusted.
Another scenario involves request filtering after mTLS authentication. ASP.NET may use regex to validate headers, cookies, or route parameters that are populated from certificate claims or custom extensions. If these regexes are not carefully designed, an attacker with a valid certificate (obtained legitimately or via a compromised CA) can send requests that trigger exponential backtracking. Because mTLS reduces reliance on other authentication checks, the application might process more complex transformations on certificate-derived data, increasing the likelihood of encountering nested quantifiers or ambiguous groupings. The key risk is not that mTLS weakens security, but that it can create a false sense of security, causing teams to overlook regex efficiency in authenticated paths, which compounds the impact of ReDoS in an otherwise trusted channel.
Mutual Tls-Specific Remediation in Aspnet — concrete code fixes
Mitigating ReDoS in ASP.NET with mTLS requires both secure regex practices and correct mTLS configuration. On the regex side, avoid nested quantifiers, use atomic groups or possessive quantifiers where supported, and prefer lazy matching with boundaries. For certificate data, validate length and character classes before applying regex, and use compiled regex with timeouts. Below are concrete code examples for an ASP.NET Core application that enforces mTLS and safely processes certificate fields.
Enabling Mutual TLS in ASP.NET Core
Configure Kestrel to require client certificates and map claims. Use the built-in certificate validation APIs to inspect the certificate before regex processing.
// Program.cs or Startup configuration
var builder = WebApplication.CreateBuilder(args);
// Require client certificates
builder.WebHost.ConfigureKestrel(serverOptions =>
{
serverOptions.ConfigureHttpsDefaults(httpsOptions =>
{
httpsOptions.ClientCertificateMode = ClientCertificateMode.RequireCertificate;
httpsOptions.AllowedCipherSuites = new[]
{
// Use strong cipher suites that support client certificate authentication
System.Security.Authentication.CipherSuiteType.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
System.Security.Authentication.CipherSuiteType.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
};
});
});
// Optionally add a custom certificate validator
builder.Services.AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme)
.AddCertificate(options =>
{
options.AllowedCertificateTypes = CertificateTypes.All;
options.RevocationMode = X509RevocationMode.NoCheck; // Set based on policy
options.Events = new CertificateAuthenticationEvents
{
OnCertificateValidated = context =>
{
// Safe validation: inspect certificate fields with bounded operations
var subject = context.ClientCertificate.Subject;
// Use a safe extraction helper instead of raw regex on untrusted input
if (!TryExtractCommonName(subject, out var commonName) || commonName.Length > 256)
{
context.Fail("Invalid certificate subject");
return;
}
// Store validated claim
var claims = new List<Claim>
{
new Claim(ClaimTypes.Name, commonName)
};
context.Principal = new ClaimsPrincipal(new ClaimsIdentity(claims, context.Scheme.Name));
context.Success();
return Task.CompletedTask;
}
};
});
var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
// Helper to avoid regex on raw subject; prefer parsing via X500DistinguishedName
bool TryExtractCommonName(string subject, out string commonName)
{
// Simple parsing for CN=...; in production, use X500DistinguishedName or a robust library
commonName = string.Empty;
if (string.IsNullOrEmpty(subject)) return false;
var cnIndex = subject.IndexOf("CN=", StringComparison.OrdinalIgnoreCase);
if (cnIndex == -1) return false;
var start = cnIndex + 3;
var end = subject.IndexOf(',', start);
if (end == -1) end = subject.Length;
commonName = subject[start..end];
return commonName.Length > 0 && commonName.Length <= 256;
}
Safe Regex Patterns for Certificate-Derived Data
If regex is necessary (e.g., to validate a custom extension), use bounded input and avoid catastrophic backtracking.
using System.Text.RegularExpressions;
public static class SafeRegex
{
// Example: validate a certificate serial number format (hex, fixed length)
private static readonly Regex SerialRegex = new Regex(
@\A[0-9A-Fa-f]{1,64}\z, // bounded length, no nested quantifiers
RegexOptions.Compiled | RegexOptions.CultureInvariant);
public static bool IsValidSerial(string value)
{
if (string.IsNullOrEmpty(value) || value.Length > 64) return false;
return SerialRegex.IsMatch(value);
}
// Example: extract a claim value safely with length checks
public static bool TryExtractClaimValue(string input, out string value)
{
value = string.Empty;
if (string.IsNullOrEmpty(input) || input.Length > 512) return false;
// Avoid overlapping groups and unbounded repeats
var pattern = @\"key=(?'val'[^&]+)\";
var match = Regex.Match(input, pattern, RegexOptions.Compiled);
if (!match.Success) return false;
value = match.Groups["val"].Value;
return value.Length <= 256;
}
}
Middleware to Reject Suspicious Requests
Add a lightweight check before regex processing to drop obviously malicious payloads that could trigger ReDoS even with safe patterns.
app.Use(async (context, next) =>
{
var request = context.Request;
// Example: reject overly long query strings or headers that may contain crafted regex inputs
if (request.QueryString.HasValue && request.QueryString.Value.Length > 1024)
{
context.Response.StatusCode = 400;
return;
}
// Inspect headers derived from mTLS claims if necessary
await next();
});
By combining enforced mTLS with disciplined regex usage, you reduce both authentication bypass risks and ReDoS exposure. middleBrick can help verify these configurations by scanning your endpoints and highlighting regex-related findings within the Authentication and Input Validation checks.
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 |