Regex Dos with Bearer Tokens
How Regex DoS Manifests in Bearer Tokens
Regular Expression Denial of Service (ReDoS) in Bearer Token validation represents a critical vulnerability where carefully crafted input causes exponential backtracking in regex engines, potentially crashing authentication systems. This attack targets the very first line of defense in API security—the token validation step.
Consider a common but vulnerable Bearer Token regex pattern:
const vulnerableRegex = /^[A-Za-z0-9-_=]+ 2e[A-Za-z0-9-_=]+$/;This pattern validates JWT-like tokens with a dot separator. The vulnerability emerges from nested quantifiers: + followed by + in the character classes. An attacker can craft input that forces the regex engine into catastrophic backtracking.
Here's how the attack works:
const maliciousToken = 'A'.repeat(20) + '.' + 'B'.repeat(20) + 'C';
const vulnerableRegex = /^[A-Za-z0-9-_=]+ 2e[A-Za-z0-9-_=]+$/;The regex engine attempts to match the first + with as many characters as possible (greedy matching), then backtracks when it encounters the dot. For each character in the first segment, the engine must try all possible positions for the dot, creating O(2^n) complexity. With just 20 characters per segment, this can take seconds to evaluate—long enough to tie up server resources.
In Bearer Token validation, this becomes particularly dangerous because:
- Authentication endpoints are often unauthenticated and publicly accessible
- Attackers can send numerous requests without credentials
- Failed validation attempts occur frequently in production
- Rate limiting may not catch slow-but-valid requests
Real-world impact: A fintech API processing payment authorizations experienced a 30-second delay on token validation, causing timeouts across their payment processing pipeline. The culprit was a nested regex in their Bearer Token middleware.
Bearer Token-Specific Detection
Detecting ReDoS vulnerabilities in Bearer Token validation requires both static analysis and runtime monitoring. Here are Bearer Token-specific detection strategies:
Static Code Analysis
Examine your Bearer Token validation code for these red flags:
// Vulnerable patterns to search for:
// 1. Nested quantifiers
const regex1 = /^[a-z]+ 2e[a-z]+$/; // BAD: nested +
// 2. Alternations with overlapping patterns
const regex2 = /^(a+)+$/; // BAD: catastrophic backtracking
// 3. Quantifiers with nested groups
const regex3 = /^([a-z]*[0-9]*)+$/; // BAD: exponential complexityRuntime Monitoring
Implement timing checks in your Bearer Token validation:
function validateBearerToken(token) {
const startTime = process.hrtime.bigint();
// Your validation logic here
const isValid = safeTokenValidation(token);
const endTime = process.hrtime.bigint();
const duration = Number(endTime - startTime) / 1000000; // ms
if (duration > 100) { // 100ms threshold
console.warn(`Bearer Token validation took ${duration}ms`, token.substring(0, 20));
// Consider logging to monitoring system
}
return isValid;
}Automated Scanning with middleBrick
middleBrick's API security scanner specifically tests for ReDoS vulnerabilities in Bearer Token endpoints:
$ middlebrick scan https://api.example.com/auth/me
# middleBrick tests with crafted payloads designed to trigger backtracking
# and measures response times to detect potential ReDoS vulnerabilities
The scanner generates attack payloads based on known regex anti-patterns and evaluates whether the endpoint exhibits timing anomalies consistent with catastrophic backtracking.
Security Headers & Rate Limiting
While not detection per se, these mitigations help identify abuse patterns:
// Express.js middleware for Bearer Token endpoints
app.use('/api/auth', (req, res, next) => {
res.setHeader('X-RateLimit-Limit', '100');
res.setHeader('X-RateLimit-Remaining', '100');
next();
});Bearer Token-Specific Remediation
Remediating ReDoS vulnerabilities in Bearer Token validation requires a multi-layered approach. Here are Bearer Token-specific solutions:
1. Replace Vulnerable Regex with Safe Alternatives
Instead of complex regex, use structured validation:
// Vulnerable
const vulnerable = /^[A-Za-z0-9-_=]+ 2e[A-Za-z0-9-_=]+$/;Replace with:
// Safe: split and validate segments
function validateBearerToken(token) {
if (typeof token !== 'string') return false;
const parts = token.split('.');
if (parts.length !== 3) return false; // JWT has 3 parts
for (const part of parts) {
// Check for invalid characters using simple includes
if (part.includes(' ') || part.includes(' ')) return false;
// Length limits prevent large input attacks
if (part.length > 1000) return false;
}
return true;
}2. Use Possessive Quantifiers (Java/.NET)
If you must use regex, leverage possessive quantifiers to prevent backtracking:
// Java/.NET specific - prevents backtracking
String pattern = "^[A-Za-z0-9-_=]+ 2e[A-Za-z0-9-_=]+$"; // No backtracking
// In Java: use possessive quantifier +?
String safePattern = "^[A-Za-z0-9-_=]++ 2e[A-Za-z0-9-_=]++$";
3. Implement Timeout-Based Validation
function validateWithTimeout(token, timeoutMs = 100) {
return new Promise((resolve) => {
const timeoutId = setTimeout(() => {
resolve(false); // Timeout - treat as invalid
}, timeoutMs);
const isValid = validateBearerToken(token); // Your validation logic
clearTimeout(timeoutId);
resolve(isValid);
});
}4. Use MiddleBrick for Continuous Monitoring
Integrate middleBrick's continuous monitoring to catch ReDoS regressions:
# GitHub Action for CI/CD pipeline
- name: middleBrick API Security Scan
uses: middlebrick/middlebrick-action@v1
with:
target_url: ${{ secrets.API_URL }}
scan_type: bearer-token
fail_if_score_below: 80
env:
MIDDLEBRICK_API_KEY: ${{ secrets.MIDDLEBRICK_API_KEY }}5. Input Length Limiting
Always enforce maximum lengths on Bearer Tokens:
function safeBearerTokenValidation(token) {
MAX_BEARER_TOKEN_LENGTH) {
6. Whitelist Character Sets
Be specific about allowed characters rather than using broad character classes:
// Specific whitelist instead of broad [A-Za-z0-9-_=]
const VALID_CHARACTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_=.';
function validateBearerToken(token) {
for (const char of token) {
// Additional structural validation
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 Bearer Token validation is vulnerable to ReDoS?
Craft malicious input with nested patterns and measure response times. For example, test with tokens containing repeated characters separated by dots, like A'.repeat(20) + '.' + 'B'.repeat(20). If validation takes more than 100ms, you likely have a vulnerability. Use middleBrick's automated scanning to test systematically without manual payload crafting.
Does ReDoS affect all regex implementations equally?
No. Different regex engines handle backtracking differently. NFA (Non-deterministic Finite Automaton) engines like those in JavaScript, Python, and Ruby are highly susceptible to catastrophic backtracking. DFA (Deterministic Finite Automaton) engines like in Rust's regex crate or Go's regexp package are immune to ReDoS. Always test your specific implementation and consider using libraries with timeout support or possessive quantifiers where available.