Regex Dos with Basic Auth
How Regex Dos Manifests in Basic Auth
Regex Denial of Service (ReDoS) in Basic Auth contexts occurs when authentication logic uses vulnerable regular expressions to validate credentials, creating a computational complexity trap that attackers can exploit to exhaust server resources.
The most common Basic Auth vulnerability involves credential validation patterns like this:
const isValidBasicAuth = (username, password) => {
const pattern = /^([a-zA-Z0-9]+)@([a-zA-Z0-9]+)\.([a-zA-Z0-9]+)$/;
return pattern.test(username) && pattern.test(password);
};
This appears benign but becomes catastrophic when paired with regex engines that use backtracking. The pattern ([a-zA-Z0-9]+) creates exponential time complexity for certain inputs. An attacker sending aaaaaaaaaaa! as both username and password triggers catastrophic backtracking, consuming CPU cycles for seconds or minutes.
Real-world exploitation patterns include:
- Credential stuffing amplification: Attackers send slightly malformed credentials that force the regex engine to explore thousands of backtracking paths
- Timing attack vectors: The variable response times from regex evaluation leak information about password structure
- Resource exhaustion cascades: A single malicious request can tie up worker threads, preventing legitimate authentication attempts
- Denial of service amplification: Multiple concurrent ReDoS requests can exhaust CPU resources entirely
The vulnerability is particularly insidious in Basic Auth because it sits in the authentication layer—the first security check. A successful ReDoS attack blocks all subsequent security controls, creating a single point of failure.
Basic Auth-Specific Detection
Detecting ReDoS vulnerabilities in Basic Auth requires analyzing both the regex patterns and their runtime behavior. Static analysis tools often miss these issues because the problematic patterns appear valid syntactically.
Key detection patterns for Basic Auth implementations:
// Vulnerable pattern examples to scan for
const dangerousPatterns = [
/(a+)+b/, // Exponential backtracking
/([a-z]+)+$/, // Nested quantifiers
/(a|aa)+b/, // Alternating patterns
/([0-9]+)*[a-z]/ // Optional groups with quantifiers
];
Runtime detection requires monitoring authentication endpoints for:
- Response time anomalies: Authentication responses that vary by seconds indicate regex evaluation problems
- CPU utilization spikes: Authentication requests correlating with CPU load increases
- Thread pool exhaustion: Authentication failures causing worker thread starvation
middleBrick's Basic Auth scanner specifically targets these vulnerabilities by:
- Analyzing credential validation regex patterns for exponential complexity
- Testing with crafted inputs designed to trigger catastrophic backtracking
- Measuring response time variance across authentication attempts
- Identifying nested quantifiers and overlapping patterns
The scanner tests patterns like:
// Test inputs for ReDoS detection
const testInputs = [
'a'.repeat(10) + '!', // Simple backtracking trigger
'a'.repeat(20) + 'b', // Exponential trigger
'a'.repeat(15) + 'b' + 'a'.repeat(15), // Alternating pattern
];
Security teams should also monitor authentication logs for:
- Requests with unusual credential lengths (extremely long or oddly structured)
- Authentication attempts that take significantly longer than average
- Failed logins with patterns suggesting regex exploitation attempts
Basic Auth-Specific Remediation
Remediating ReDoS in Basic Auth requires replacing vulnerable regex patterns with safe alternatives and implementing proper validation strategies. The most effective approach combines input validation, safe pattern matching, and rate limiting.
Safe Basic Auth credential validation:
// Safe username/password validation
const validateBasicAuth = (username, password) => {
// Length limits prevent resource exhaustion
if (username.length > 255 || password.length > 255) {
return false;
}
// Use non-backtracking patterns or direct string methods
const isValid = (input) => {
// Simple character class validation without quantifiers
for (let char of input) {
if (!char.match(/[a-zA-Z0-9]/)) {
return false;
}
}
return true;
};
return isValid(username) && isValid(password);
};
Alternative safe approaches:
// Using built-in string methods (no regex)
const validateWithoutRegex = (username, password) => {
const isSafe = (input) => {
return /^[a-zA-Z0-9]+$/.test(input); // Simple pattern, no backtracking
};
return isSafe(username) && isSafe(password);
};
// Precompiled safe patterns
const safePattern = /^[a-zA-Z0-9]{1,255}$/;
const validateWithSafePattern = (username, password) => {
return safePattern.test(username) && safePattern.test(password);
};
Additional protective measures:
- Timeouts: Implement authentication timeouts to prevent long-running regex evaluations
- Rate limiting: Limit authentication attempts per IP or user to reduce ReDoS impact
- Input sanitization: Reject credentials with suspicious patterns before regex evaluation
- Monitoring: Alert on authentication response times exceeding thresholds
Framework-specific implementations:
// Express.js middleware with protection
const express = require('express');
const rateLimit = require('express-rate-limit');
const authLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 5, // limit each IP to 5 requests per windowMs
message: 'Too many authentication attempts'
});
const basicAuthMiddleware = (req, res, next) => {
const authHeader = req.headers.authorization;
if (!authHeader || !authHeader.startsWith('Basic ')) {
return res.status(401).send('Missing Basic Auth');
}
try {
const base64Credentials = authHeader.split(' ')[1];
const credentials = Buffer.from(base64Credentials, 'base64').toString('ascii');
const [username, password] = credentials.split(':');
// Safe validation with timeout
const validationTimeout = setTimeout(() => {
return res.status(429).send('Authentication timeout');
}, 100); // 100ms timeout
const isValid = validateBasicAuth(username, password);
clearTimeout(validationTimeout);
if (!isValid) {
return res.status(401).send('Invalid credentials');
}
next();
} catch (error) {
return res.status(401).send('Invalid credentials');
}
};
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 |