Regex Dos with Mutual Tls
How Regex DoS Manifests in Mutual TLS
Regular Expression Denial of Service (Regex DoS), also known as ReDoS, occurs when an attacker crafts input that causes a regex engine to consume exponential time during pattern matching. In Mutual TLS (mTLS) implementations, this vulnerability can manifest in several critical code paths that handle certificate validation, authentication headers, and certificate revocation checks.
The most common attack vector targets certificate subject fields during mTLS handshake validation. Consider a certificate validation function that uses regex to parse the Subject Alternative Name (SAN) field:
import re
def validate_san(san_string):
pattern = r'DNS:([a-zA-Z0-9.-]+)'
return bool(re.search(pattern, san_string))
# Vulnerable to ReDoS with input like:
vulnerable_input = 'DNS:a'*1000 + 'b'*1000 + 'c'*1000This pattern contains nested quantifiers that can cause catastrophic backtracking. An attacker submitting a certificate with a crafted SAN field containing alternating character sequences can force the regex engine to evaluate billions of possible matches, effectively blocking the TLS handshake process.
Another mTLS-specific attack surface exists in certificate chain validation. Many implementations use regex to validate certificate chain formats or extract specific fields from PEM-encoded certificates:
func parseCertificatePEM(pemData string) ([]string, error) {
pattern := `-----BEGIN CERTIFICATE-----(.*?)-----END CERTIFICATE-----`
re := regexp.MustCompile(pattern)
matches := re.FindAllStringSubmatch(pemData, -1)
return matches, nil
}
// Vulnerable to input like:
vulnerablePEM = "-----BEGIN CERTIFICATE-----
" + "A"*10000 + "
" + "B"*10000 + "
" + "C"*10000The non-greedy quantifier (.*?) combined with large input creates the same exponential time complexity. In mTLS contexts, this can prevent certificate chain validation, causing legitimate clients to be unable to establish secure connections.
Authentication middleware that validates mTLS client certificates often contains similar vulnerabilities. A common pattern uses regex to extract and validate certificate metadata:
function validateClientCert(certString) {
const pattern = /CN=([^,]+),OU=([^,]+),O=([^,]+)/;
const match = certString.match(pattern);
if (!match) return false;
// Vulnerable to ReDoS if match[1], match[2], or match[3] contain crafted input
return match[1].length < 100 && match[2].length < 100;
}An attacker can submit a certificate with carefully crafted Common Name (CN) or Organizational Unit (OU) fields that trigger exponential backtracking in the regex engine, causing the authentication check to hang indefinitely.
Mutual TLS-Specific Detection
Detecting Regex DoS in mTLS implementations requires both static analysis and runtime testing. Static analysis tools can identify vulnerable regex patterns, but mTLS-specific detection must account for certificate processing contexts.
Static analysis should flag these patterns in mTLS-related code:
# Look for vulnerable regex patterns in certificate processing code
rgrep -n '([a-zA-Z0-9.-]+)' *.py
rgrep -n '(.*?)' *.go
rgrep -n '([^,]+)' *.js
Focus on files containing keywords like "cert", "tls", "mTLS", "certificate", "handshake", and "auth". Pay special attention to functions that process certificate fields, validate certificate chains, or extract metadata from PEM data.
Runtime detection with middleBrick's API security scanner can identify active Regex DoS vulnerabilities in mTLS endpoints. The scanner tests certificate processing endpoints with crafted inputs designed to trigger exponential backtracking:
# Scan an mTLS API endpoint for Regex DoS vulnerabilities
middlebrick scan https://api.example.com/auth \
--test-mtls \
--cert client-cert.pem \
--key client-key.pemmiddleBrick specifically tests mTLS certificate processing endpoints by submitting certificates with crafted SAN fields, subject fields, and PEM data containing patterns that trigger ReDoS. The scanner measures response times and flags endpoints where processing takes significantly longer than baseline, indicating potential regex vulnerabilities.
Manual testing for mTLS-specific ReDoS involves creating test certificates with crafted fields:
# Create a test certificate with vulnerable SAN field
openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem \
-days 365 -nodes -subj "/CN=Test" \
-addext "subjectAltName=DNS:$(python3 -c 'print("a"*1000 + "b"*1000 + "c"*1000)')"Test the endpoint with this certificate and monitor for abnormal processing times or timeouts. A healthy mTLS implementation should process even crafted certificates in milliseconds, while vulnerable implementations may hang for seconds or minutes.
Network-level detection can identify ReDoS attacks in progress by monitoring for unusual patterns in TLS handshake timing. Sudden increases in handshake duration or repeated connection attempts with similar certificate patterns may indicate active exploitation attempts.
Mutual TLS-Specific Remediation
Remediating Regex DoS in mTLS implementations requires replacing vulnerable regex patterns with safer alternatives and implementing proper input validation. The most effective approach combines multiple strategies tailored to mTLS contexts.
First, replace vulnerable regex patterns with non-backtracking alternatives. For certificate field validation, use explicit character-by-character validation instead of regex:
def validate_san_safe(san_string):
# Split on DNS: prefix and validate each component
parts = san_string.split('DNS:')
for part in parts[1:]: # Skip first part (before first DNS:)
if not part or len(part) > 253: # DNS label max length
return False
labels = part.split('.')
for label in labels:
if not label or len(label) > 63: # DNS label max length
return False
if not all(c.isalnum() or c in '-_' for c in label):
return False
return TrueThis approach eliminates regex entirely, using simple string operations with bounded iteration time. The validation runs in O(n) time regardless of input complexity, preventing ReDoS attacks.
For certificate chain validation, use streaming parsers instead of regex:
func parseCertificatePEMSafe(pemData string) ([]string, error) {
const certStart = "-----BEGIN CERTIFICATE-----"
const certEnd = "-----END CERTIFICATE-----"
var certs []string
scanner := bufio.NewScanner(strings.NewReader(pemData))
var currentCert strings.Builder
inCert := false
for scanner.Scan() {
line := scanner.Text()
if line == certStart {
inCert = true
currentCert.Reset()
currentCert.WriteString(line + "\n")
} else if line == certEnd && inCert {
currentCert.WriteString(line)
certs = append(certs, currentCert.String())
inCert = false
} else if inCert {
currentCert.WriteString(line + "\n")
}
}
if inCert {
return nil, errors.New("incomplete certificate")
}
return certs, nil
}This streaming approach processes certificates line by line without regex, eliminating backtracking vulnerabilities. It also provides better error handling for malformed certificates.
Implement input length limits and timeouts for all certificate processing operations:
const MAX_CERTIFICATE_SIZE = 10240; // 10KB
const CERT_PROCESSING_TIMEOUT = 1000; // 1 second
function validateClientCertWithTimeout(certString) {
return new Promise((resolve, reject) => {
const timeoutId = setTimeout(() => {
reject(new Error('Certificate processing timeout'));
}, CERT_PROCESSING_TIMEOUT);
try {
const isValid = validateClientCertSafe(certString);
clearTimeout(timeoutId);
resolve(isValid);
} catch (error) {
clearTimeout(timeoutId);
reject(error);
}
});
}Timeouts prevent even vulnerable implementations from being completely blocked by ReDoS attacks. Combined with input size limits, this creates a defense-in-depth approach.
Consider using safe-regex libraries that analyze regex patterns for potential exponential runtime:
import safe_regex
# Check if a regex pattern is safe before using it
pattern = r'DNS:([a-zA-Z0-9.-]+)'
if not safe_regex.is_safe(pattern):
raise ValueError('Unsafe regex pattern detected')While safe-regex isn't perfect, it provides an additional layer of protection by flagging the most dangerous patterns before they can be deployed.
For mTLS implementations using third-party libraries, ensure you're using the latest versions, as many libraries have fixed known ReDoS vulnerabilities in certificate processing code. Regular dependency updates are crucial for maintaining security against these attacks.
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 |
Frequently Asked Questions
How can I test if my mTLS implementation is vulnerable to Regex DoS?
Use middleBrick's API security scanner to test your mTLS endpoints. The scanner submits crafted certificates with ReDoS-triggering patterns and measures processing times. Look for endpoints where processing takes significantly longer than normal (more than 2-3x baseline). You can also manually create test certificates with crafted SAN fields containing alternating character sequences and monitor handshake times using tools like Wireshark or tcpdump.
Are there specific regex patterns that are safe to use in mTLS certificate processing?
Yes, use regex patterns with atomic grouping, possessive quantifiers, or limited repetition that prevent backtracking. For example, use (?>...) atomic groups in Perl-compatible regex engines, or limit quantifiers with specific bounds like {0,10} instead of +. However, the safest approach is to avoid regex entirely for certificate processing and use explicit string validation or streaming parsers that operate in O(n) time regardless of input complexity.