HIGH denial of servicebasic auth

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

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 IDNameSeverity
CWE-400Uncontrolled Resource Consumption HIGH
CWE-770Allocation of Resources Without Limits MEDIUM
CWE-799Improper Control of Interaction Frequency MEDIUM
CWE-835Infinite Loop HIGH
CWE-1050Excessive Platform Resource Consumption MEDIUM

Frequently Asked Questions

Why is Basic Auth more vulnerable to DoS than token-based authentication?
Basic Auth sends credentials with every request, forcing the server to perform authentication operations repeatedly. Token-based systems validate a pre-generated token, which is typically a simple lookup or cryptographic verification. Basic Auth also lacks built-in expiration and revocation mechanisms, making it harder to mitigate ongoing attacks.
Can I use Basic Auth safely in production environments?
Basic Auth can be used safely with proper protections: always use HTTPS to prevent credential interception, implement aggressive rate limiting, add account lockout mechanisms, and consider using it only for non-critical endpoints. For production APIs handling sensitive operations, token-based authentication with short-lived tokens is generally more secure and DoS-resistant.