Denial Of Service with Basic Auth
How Denial Of Service Manifests in Basic Auth
Denial of Service (DoS) attacks against Basic Auth endpoints exploit the authentication mechanism's inherent characteristics. Unlike token-based systems where credentials can be rotated or revoked quickly, Basic Auth relies on static username/password pairs that remain valid until explicitly changed. This creates several attack vectors:
Credential Brute-Force Amplification occurs because Basic Auth sends credentials with every request. An attacker can send thousands of authentication attempts per second without triggering most rate limiting systems, since each attempt appears as a unique HTTP request. The server must process the Authorization header, decode the Base64 payload, and validate credentials for each attempt.
Memory Exhaustion via Authentication State happens when authentication middleware creates session objects or user context even for failed logins. In Node.js applications using Express, for example:
app.use((req, res, next) => {
const authHeader = req.headers.authorization;
if (authHeader) {
const [type, credentials] = authHeader.split(' ');
if (type === 'Basic') {
const [username, password] = Buffer.from(credentials, 'base64')
.toString('utf8')
.split(':');
// Even failed auth creates user object
req.user = authenticate(username, password);
}
}
next();
});
Each failed authentication creates objects in memory that the garbage collector must eventually clean up, causing memory pressure under sustained attack.
CPU Exhaustion through Cryptographic Operations can occur when authentication systems use computationally expensive password hashing (bcrypt, scrypt) for every request. While this protects against credential theft, it becomes a DoS vector:
const bcrypt = require('bcrypt');
function authenticate(username, password) {
const user = findUserByUsername(username);
if (!user) return null;
// CPU-intensive operation on every request
return bcrypt.compare(password, user.passwordHash);
}
Under attack, the CPU spends all cycles on password comparisons instead of serving legitimate traffic.
Network Amplification is particularly effective with Basic Auth because the Authorization header (typically 40-80 bytes) triggers a full authentication workflow that may involve database queries, external authentication services, or complex business logic. The computational cost-to-network-cost ratio makes this an efficient attack vector.
Basic Auth-Specific Detection
Detecting DoS vulnerabilities in Basic Auth requires examining both the authentication implementation and the surrounding infrastructure. Here's how to identify these issues:
Authentication Endpoint Analysis should verify that authentication handlers don't create unnecessary state. Look for patterns where failed authentication still allocates resources:
// Vulnerable pattern - creates user object even for failed auth
app.post('/login', (req, res) => {
const { username, password } = req.body;
const user = db.findUser(username);
if (!user || user.password !== password) {
req.user = null; // Still created user object
return res.status(401).json({ error: 'Invalid credentials' });
}
req.user = user;
res.json({ token: generateToken(user) });
});
Rate Limiting Verification is critical. Basic Auth endpoints often lack proper rate limiting because developers assume the authentication itself provides protection. Check if your API implements:
const rateLimit = require('express-rate-limit');
// Must rate limit at authentication endpoint
const authLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 5, // limit each IP to 5 requests per windowMs
message: 'Too many authentication attempts'
});
app.post('/login', authLimiter, (req, res) => {
// Authentication logic
});
Resource Usage Monitoring during authentication attempts reveals vulnerabilities. Use tools like ab (Apache Bench) or hey to simulate attack conditions:
# Test authentication endpoint with 1000 requests
hey -n 1000 -c 100 http://api.example.com/protected
Monitor CPU, memory, and response times. A vulnerable Basic Auth endpoint will show:
- Linear increase in response time as request volume increases
- Memory usage growing proportionally to request count
- CPU utilization spiking during authentication attempts
middleBrick API Security Scanning automatically detects these DoS patterns in Basic Auth implementations. The scanner tests authentication endpoints with varying request rates and analyzes response characteristics to identify amplification factors and resource exhaustion patterns.
Basic Auth-Specific Remediation
Securing Basic Auth against DoS attacks requires architectural changes and defensive coding patterns. Here are specific remediation strategies:
Implement Request Throttling at the Network Layer before authentication even occurs:
// Express middleware for pre-authentication throttling
function basicAuthThrottle(req, res, next) {
const clientIP = req.ip;
const now = Date.now();
// Store request timestamps in memory or cache
const requests = throttleStore.get(clientIP) || [];
const recentRequests = requests.filter(ts => now - ts < 60000);
if (recentRequests.length > 10) {
return res.status(429).json({
error: 'Rate limit exceeded - too many auth attempts'
});
}
recentRequests.push(now);
throttleStore.set(clientIP, recentRequests);
next();
}
Optimize Authentication Workflows to minimize resource consumption:
const crypto = require('crypto');
// Fast-path for obviously invalid credentials
function quickReject(username, password) {
// Check for common attack patterns
if (password.length > 100 || password.includes(' ')) {
return true;
}
// Check if username exists before expensive operations
if (!userCache.has(username)) {
return true;
}
return false;
}
function authenticate(username, password) {
if (quickReject(username, password)) {
return null;
}
const user = userCache.get(username);
if (!user) return null;
// Use constant-time comparison to prevent timing attacks
const valid = crypto.timingSafeEqual(
Buffer.from(password),
Buffer.from(user.password)
);
return valid ? user : null;
}
Implement Account Lockout Mechanisms with exponential backoff:
const accountLocks = new Map();
function checkAccountLock(username) {
const lockInfo = accountLocks.get(username);
if (!lockInfo) return false;
const { until, attempts } = lockInfo;
if (Date.now() < until) {
return true;
}
// Reset after lock expires
if (attempts >= 5) {
accountLocks.delete(username);
}
return false;
}
function recordFailedAttempt(username) {
const lockInfo = accountLocks.get(username) || { attempts: 0 };
lockInfo.attempts++;
if (lockInfo.attempts >= 5) {
// Exponential backoff: 1min, 5min, 15min, 1hour
const multipliers = [1, 5, 15, 60];
const multiplier = multipliers[Math.min(lockInfo.attempts - 5, 3)];
lockInfo.until = Date.now() + (multiplier * 60 * 1000);
}
accountLocks.set(username, lockInfo);
}
Deploy Rate Limiting with Authentication-Aware Rules using middleware that distinguishes between authentication and regular API usage:
const rateLimit = require('express-rate-limit');
// Separate limits for auth vs regular API
const authRateLimiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 10, // 10 auth attempts per 15 minutes
message: 'Too many authentication attempts',
skip: (req) => !req.headers.authorization
});
const apiRateLimiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 100, // 100 API requests per 15 minutes
message: 'Too many requests',
skip: (req) => req.headers.authorization
});
app.use('/api/protected/*', apiRateLimiter);
app.use('/api/auth/*', authRateLimiter);
Monitor and Alert on Authentication Patterns to detect ongoing attacks:
const winston = require('winston');
const authLogger = winston.createLogger({
transports: [
new winston.transports.File({ filename: 'auth.log' })
]
});
function logAuthAttempt(username, success, ip) {
authLogger.info(`Auth attempt: ${success ? 'SUCCESS' : 'FAIL'}`, {
username,
ip,
timestamp: new Date().toISOString()
});
// Alert on suspicious patterns
if (!success && shouldAlert(username, ip)) {
alertAdmin(`Suspicious auth attempts from ${ip} for user ${username}`);
}
}
Related CWEs: resourceConsumption
| CWE ID | Name | Severity |
|---|---|---|
| CWE-400 | Uncontrolled Resource Consumption | HIGH |
| CWE-770 | Allocation of Resources Without Limits | MEDIUM |
| CWE-799 | Improper Control of Interaction Frequency | MEDIUM |
| CWE-835 | Infinite Loop | HIGH |
| CWE-1050 | Excessive Platform Resource Consumption | MEDIUM |