Weakness reference
CWE-294

Authentication Bypass by Capture-replay

A capture-replay vulnerability occurs when an attacker can record a legitimate user's authentication traffic and replay it later to gain unauthorized access…

01Summary

A capture-replay vulnerability occurs when an attacker can record a legitimate user's authentication traffic and replay it later to gain unauthorized access without knowing the user's actual credentials. This happens when authentication mechanisms lack protections against reuse of previously captured authentication data. The weakness is particularly dangerous because it requires no password cracking or social engineering — only the ability to intercept and resend network traffic.

02How It Happens

Authentication systems are vulnerable to capture-replay attacks when they fail to include mechanisms that ensure each authentication attempt is unique and cannot be reused. Common causes include:

- Lack of nonce or timestamp validation:
The server accepts the same authentication token or response indefinitely, or without checking that it was recently generated. - No session binding:
Authentication credentials are not tied to a specific session, connection, or device identifier, making them portable across contexts. - Unencrypted or weakly encrypted channels:
Even if the protocol itself is sound, transmitting authentication data over unencrypted connections (HTTP instead of HTTPS) allows trivial interception. - Stateless authentication without integrity checks:
Systems that rely on client-supplied tokens without cryptographic verification of freshness or origin.

The attacker's role is passive until the replay phase — they simply capture valid authentication traffic and retransmit it, often without modification.

03Real-World Impact

Successful replay attacks grant an attacker the same access level as the legitimate user whose traffic was captured. This can lead to account takeover, unauthorized data access, privilege escalation if the captured session belongs to an administrator, or lateral movement within a system. Unlike password-based breaches, the victim may not realize their account has been compromised because their password remains unchanged and their legitimate sessions continue to work normally.

04Vulnerable & Fixed Patterns

Vulnerable pattern
import hashlib

def authenticate_user(username, password):
    # Server stores: username -> password_hash
    stored_hash = get_stored_hash(username)
    
    # Client sends: username + hash(password)
    client_hash = hashlib.sha256(password.encode()).hexdigest()
    
    if client_hash == stored_hash:
        return generate_session_token(username)
    return None

def verify_session(token):
    # Token is never invalidated; same token works forever
    username = decode_token(token)
    return username is not None

Why it's vulnerable:
The authentication hash is deterministic and never changes. An attacker who captures the hash can replay it indefinitely to authenticate as that user. There is no nonce, timestamp, or one-time-use mechanism to prevent reuse.

Fixed pattern
import hashlib
import secrets
import time

def authenticate_user(username, password, nonce):
    # Server generates a fresh nonce for each authentication attempt
    stored_hash = get_stored_hash(username)
    
    # Client computes: hash(password + nonce)
    client_response = hashlib.sha256(
        (password + nonce).encode()
    ).hexdigest()
    
    # Verify response and check nonce hasn't been used before
    if client_response == stored_hash and not nonce_used(nonce):
        mark_nonce_used(nonce)
        return generate_session_token(username)
    return None

def generate_session_token(username):
    # Session token is short-lived and server-side validated
    token = secrets.token_urlsafe(32)
    store_session(token, username, expiry=time.time() + 3600)
    return token
Vulnerable pattern
<?php
// Client sends: username and md5(password)
$username = $_POST['username'];
$client_hash = $_POST['password_hash'];

$stored_hash = get_user_password_hash($username);

if ($client_hash === $stored_hash) {
    // Set a session cookie that never expires
    setcookie('auth_token', $client_hash, 0);
    $_SESSION['user'] = $username;
}
?>

Why it's vulnerable:
The authentication hash is static and reusable. An attacker who intercepts the POST request can replay the exact same request (or just resend the cookie) to regain access. There is no nonce, timestamp, or session expiration.

Fixed pattern
<?php
// Server generates a unique nonce for each login attempt
$nonce = bin2hex(random_bytes(16));
store_nonce($nonce, time());

// Client computes: hash(password + nonce)
$username = $_POST['username'];
$client_response = $_POST['response'];
$nonce = $_POST['nonce'];

$stored_hash = get_user_password_hash($username);
$expected_response = hash('sha256', $stored_hash . $nonce);

// Verify response and ensure nonce is fresh and unused
if (hash_equals($client_response, $expected_response) && 
    is_nonce_valid($nonce) && 
    !nonce_already_used($nonce)) {
    
    mark_nonce_used($nonce);
    $session_token = bin2hex(random_bytes(32));
    store_session($session_token, $username, time() + 3600);
    setcookie('session_id', $session_token, time() + 3600, '/', '', true, true);
}
?>

05Prevention Checklist

Use HTTPS for all authentication traffic
to prevent passive interception of credentials or tokens.
Implement nonce-based authentication:
Generate a unique, unpredictable nonce for each authentication attempt and verify it is used only once.
Add timestamp validation:
Include a server-verified timestamp in authentication responses and reject requests older than a short window (e.g., 5 minutes).
Use short-lived session tokens:
Issue session tokens with explicit expiration times and invalidate them on logout or after a period of inactivity.
Bind sessions to client context:
Tie session tokens to the client's IP address, user agent, or device fingerprint so replayed tokens fail if context changes.
Implement rate limiting and anomaly detection:
Monitor for multiple authentication attempts from different locations or rapid token reuse, and alert or block suspicious patterns.

06Signs You May Already Be Affected

Monitor your authentication logs for patterns such as the same user authenticating from multiple geographic locations simultaneously, or authentication events occurring at unusual times when the user was not active. Check for unexplained session activity or access to sensitive resources by accounts that should have been idle. If you observe authentication tokens or hashes being reused across multiple requests or sessions, that is a strong indicator of capture-replay vulnerability.

07Related Recent Vulnerabilities