HIGH replay attackbasic auth

Replay Attack with Basic Auth

How Replay Attack Manifests in Basic Auth

Replay attacks in Basic Authentication occur when an attacker captures valid authentication credentials and resubmits them to gain unauthorized access. Since Basic Auth transmits credentials as Base64-encoded strings in the Authorization header, these credentials can be intercepted and reused if transmitted over insecure channels.

The attack typically follows this pattern: An attacker uses network sniffing tools like Wireshark or tcpdump to capture HTTP traffic containing the Authorization header. The captured header looks like: Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=, which decodes to username:password. The attacker can then replay this exact header to the server, bypassing authentication entirely.

Basic Auth's stateless nature makes it particularly vulnerable. Unlike session-based authentication where servers track active sessions, Basic Auth validates credentials on every request. This means a captured Authorization header remains valid until the password changes or the account is disabled. The attack can be automated using tools like Burp Suite or custom scripts that continuously replay captured headers.

Real-world examples include CVE-2021-41262 where attackers exploited Basic Auth endpoints lacking rate limiting to brute force credentials, and numerous incidents where API endpoints exposed over HTTP allowed credential capture and replay. The attack is especially effective against APIs that don't implement additional protections like API keys, tokens with expiration, or IP restrictions.

Time-based replay attacks are particularly insidious. An attacker captures credentials during one session, then replays them hours or days later when the legitimate user is offline. Without proper monitoring or anomaly detection, these attacks can go unnoticed for extended periods, especially in systems where Basic Auth is used for machine-to-machine communication or internal service authentication.

Basic Auth-Specific Detection

Detecting replay attack vulnerabilities in Basic Auth requires examining both network transmission and server-side validation patterns. The first critical check is whether authentication occurs over HTTPS rather than HTTP. Using middleBrick's CLI, you can scan your endpoints for this vulnerability:

middlebrick scan https://api.example.com/auth-endpoint

The scanner examines the Authorization header transmission method and flags any endpoints accepting Basic Auth over unencrypted channels. middleBrick's black-box scanning approach means it tests the actual runtime behavior without requiring source code access.

Server-side detection involves analyzing authentication logs for unusual patterns. Look for multiple successful authentications from different IP addresses using the same credentials within short timeframes. Tools like fail2ban or custom log analyzers can flag these patterns. Additionally, check for missing rate limiting on authentication endpoints - a clear indicator that replay attacks could succeed.

Network-level detection requires monitoring for repeated identical Authorization headers. Security information and event management (SIEM) systems can be configured to alert on patterns like: same Authorization header from different source IPs, rapid succession of identical authentication attempts, or successful logins from geographically impossible locations.

middleBrick's API security scanning specifically tests for replay vulnerabilities by attempting to capture and reuse Authorization headers across different network conditions. The scanner checks if the server properly validates the request context beyond just the credentials, such as checking for request freshness, IP consistency, or implementing timestamp-based validation.

Code-level detection involves reviewing authentication middleware. Look for implementations that only check the Authorization header without additional context validation. A vulnerable implementation might look like:

def authenticate(request):
    auth_header = request.headers.get('Authorization')
    if not auth_header or not auth_header.startswith('Basic '):
        return None
    try:
        credentials = base64.b64decode(auth_header[6:]).decode('utf-8')
        username, password = credentials.split(':', 1)
        user = User.find_by_username(username)
        if user and user.check_password(password):
            return user
    except:
        return None
    return None

This code only validates credentials without any replay protection mechanisms, making it vulnerable to the attack described.

Basic Auth-Specific Remediation

Remediating replay attack vulnerabilities in Basic Auth requires implementing multiple defensive layers. The most fundamental fix is enforcing HTTPS/TLS for all authentication traffic. This prevents credential interception at the network level. In your web server configuration:

server {
    listen 443 ssl http2;
    server_name api.example.com;
    
    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;
    
    location /auth {
        # Basic Auth configuration
        auth_basic "Restricted Area";
        auth_basic_user_file /etc/nginx/.htpasswd;
    }
}

For applications where Basic Auth must be used, implement timestamp-based nonce validation. The client includes a timestamp in the username field, and the server rejects requests older than a configurable threshold:

import base64
import datetime
from typing import Optional

def validate_basic_auth(header: str, timeout_seconds: int = 300) -> Optional[User]:
    if not header or not header.startswith('Basic '):
        return None
    
    try:
        credentials = base64.b64decode(header[6:]).decode('utf-8')
        parts = credentials.split(':', 1)
        if len(parts) != 2:
            return None
            
        username, password = parts
        
        # Extract timestamp from username (format: username|timestamp)
        try:
            user_part, timestamp_str = username.rsplit('|', 1)
            timestamp = datetime.datetime.fromtimestamp(float(timestamp_str))
            
            # Check if timestamp is within valid window
            if datetime.datetime.now() - timestamp > datetime.timedelta(seconds=timeout_seconds):
                return None
                
        except ValueError:
            # Fallback for non-timestamp format
            user_part = username
        
        user = User.find_by_username(user_part)
        if user and user.check_password(password):
            return user
            
    except Exception:
        return None
    
    return None

Implement IP-based restrictions by maintaining a mapping of authenticated sessions to source IPs. Reject requests where the Authorization header was previously seen from a different IP:

const activeSessions = new Map();

function basicAuthMiddleware(req, res, next) {
    const authHeader = req.headers.authorization;
    if (!authHeader || !authHeader.startsWith('Basic ')) {
        return res.status(401).send('Missing Authorization header');
    }
    
    const credentials = Buffer.from(authHeader.split(' ')[1], 'base64').toString();
    const [username, password] = credentials.split(':');
    
    // Validate credentials
    const user = authenticateUser(username, password);
    if (!user) {
        return res.status(401).send('Invalid credentials');
    }
    
    // Check for replay from different IP
    const sessionKey = `${username}:${password}`;
    const lastIP = activeSessions.get(sessionKey);
    if (lastIP && lastIP !== req.ip) {
        console.warn(`Replay attempt detected: ${username} from ${req.ip} (last: ${lastIP})`);
        return res.status(403).send('Session conflict detected');
    }
    
    activeSessions.set(sessionKey, req.ip);
    req.user = user;
    next();
}

Rate limiting is essential for Basic Auth endpoints. Implement per-IP and per-user rate limits to prevent automated replay attacks:

from ratelimit import limits, sleep_and_retry
import time

# 5 requests per minute per IP
RATE_LIMIT = 5
TIME_PERIOD = 60

@sleep_and_retry
def rate_limited_auth_check(ip: str) -> bool:
    @limits(calls=RATE_LIMIT, period=TIME_PERIOD)
    def check():
        return True
    
    try:
        check()
        return True
    except Exception:
        return False

# Usage in authentication
if not rate_limited_auth_check(request.remote_addr):
    return Response('Rate limit exceeded', status=429)

For API services, consider migrating from Basic Auth to token-based authentication with short expiration times. JWT tokens with 5-15 minute lifetimes significantly reduce the window for successful replay attacks while maintaining usability.

Frequently Asked Questions

Can Basic Auth ever be secure against replay attacks?
Basic Auth can be made resistant to replay attacks when combined with HTTPS/TLS encryption, timestamp-based nonces, IP binding, and rate limiting. However, these additional mechanisms essentially transform Basic Auth into a more complex authentication system. For truly secure API authentication, token-based systems like JWT or OAuth2 are recommended as they natively include expiration and context validation features.
How does middleBrick detect replay attack vulnerabilities in Basic Auth?
middleBrick performs black-box scanning that tests whether Basic Auth endpoints transmit credentials over unencrypted channels, checks for missing rate limiting on authentication endpoints, and analyzes the authentication flow for replay vulnerabilities. The scanner doesn't require credentials or source code access - it examines the actual runtime behavior of your API endpoints and provides a security score with specific findings about replay attack risks.