Authentication Bypass by Capture-replay
Description
Authentication Bypass by Capture-replay is a vulnerability where attackers can sniff network traffic containing authentication credentials or commands and replay them to gain unauthorized access. Capture-replay attacks are common and can be difficult to defeat without cryptography. They are a subset of network injection attacks that rely on observing previously-sent valid commands, then resending the same commands (possibly with slight modifications) to the server. If the server cannot distinguish between fresh requests and replayed ones, the attacker achieves the same authenticated state as the original legitimate user.
Risk
Replay attacks present a significant threat to authentication systems, particularly those transmitting credentials in cleartext or using simple hash-based authentication without freshness guarantees. Attackers positioned to observe network traffic (through network sniffing, man-in-the-middle attacks, or compromised infrastructure) can capture authentication sequences and replay them indefinitely. Systems using MD5 or other hashes for password transmission are particularly vulnerable since the hash itself becomes the credential. The risk is amplified in wireless networks, shared network segments, and any environment where traffic interception is feasible. Once captured, authentication credentials can be replayed from any location, making these attacks valuable for persistent access.
Solution
Implement replay prevention mechanisms using cryptographic techniques. Add sequence numbers or timestamps combined with cryptographic signatures to ensure each message can only be used once. Use challenge-response authentication where the server provides a unique challenge for each authentication attempt. Implement nonces (numbers used once) that are included in authentication messages and tracked to prevent reuse. Use TLS for all authentication traffic to prevent network-level capture. For highly sensitive systems, implement mutual authentication with client certificates. Consider using time-synchronized one-time passwords (TOTP) that change periodically. If using hashes for authentication, include timestamps and random values in the hash computation to make each authentication request unique.
Common Consequences
| Impact | Details |
|---|---|
| Access Control | Scope: Access Control Replayed authentication messages grant attackers the same access as the original authenticated user. This enables unauthorized access to protected resources, assumption of user identity, and ability to perform actions as the victim user. |
Example Code
Vulnerable Code (Python)
The following examples demonstrate authentication vulnerable to capture-replay:
# Vulnerable: Simple hash-based authentication susceptible to replay
import hashlib
import socket
class VulnerableAuthClient:
def authenticate(self, username, password):
# Vulnerable: Hash can be captured and replayed
password_hash = hashlib.md5(password.encode()).hexdigest()
# Send credentials over network
auth_message = f"{username}:{password_hash}"
self.socket.send(auth_message.encode())
# Attacker captures auth_message, replays it later
response = self.socket.recv(1024)
return response == b"AUTH_SUCCESS"
class VulnerableAuthServer:
def handle_auth(self, client_socket):
data = client_socket.recv(1024).decode()
username, password_hash = data.split(':')
# Vulnerable: Same hash always works
stored_hash = self.get_stored_hash(username)
if password_hash == stored_hash:
# Replayed hash is accepted!
client_socket.send(b"AUTH_SUCCESS")
return True
client_socket.send(b"AUTH_FAILED")
return False
// Vulnerable: Token-based authentication without replay protection
#include <string.h>
#include <time.h>
typedef struct {
char username[64];
char token[128];
} AuthRequest;
int vulnerable_verify_token(AuthRequest *req) {
// Vulnerable: Token doesn't include timestamp or nonce
char *stored_token = get_user_token(req->username);
if (stored_token && strcmp(req->token, stored_token) == 0) {
return 1; // Captured token can be replayed forever
}
return 0;
}
// Vulnerable: Session token generation without uniqueness
char* vulnerable_generate_session(const char *username) {
// Vulnerable: Predictable, replayable session
static char session[256];
// No timestamp, no random component
snprintf(session, sizeof(session), "%s_session", username);
return session;
}
// Vulnerable: API authentication without replay protection
public class VulnerableApiAuth {
public boolean authenticate(HttpServletRequest request) {
String apiKey = request.getHeader("X-API-Key");
String signature = request.getHeader("X-Signature");
// Vulnerable: No timestamp in signature
String expectedSig = computeSignature(apiKey, request.getRequestURI());
if (signature.equals(expectedSig)) {
return true; // Same request can be replayed
}
return false;
}
private String computeSignature(String apiKey, String uri) {
// Vulnerable: Deterministic signature without time component
return hmacSha256(getSecret(apiKey), uri);
}
}
Fixed Code (Python)
# Fixed: Authentication with replay protection
import hashlib
import hmac
import secrets
import time
import socket
class SecureAuthClient:
def authenticate(self, username, password):
# Request challenge from server
self.socket.send(b"REQUEST_CHALLENGE")
challenge = self.socket.recv(1024).decode()
# Include timestamp
timestamp = str(int(time.time()))
# Compute response including challenge and timestamp
message = f"{username}:{timestamp}:{challenge}"
response_hash = hmac.new(
password.encode(),
message.encode(),
hashlib.sha256
).hexdigest()
auth_message = f"{username}:{timestamp}:{response_hash}"
self.socket.send(auth_message.encode())
return self.socket.recv(1024) == b"AUTH_SUCCESS"
class SecureAuthServer:
def __init__(self):
self.used_challenges = {} # Track used challenges
self.challenge_timeout = 300 # 5 minutes
def generate_challenge(self):
challenge = secrets.token_hex(32)
self.used_challenges[challenge] = time.time()
return challenge
def handle_auth(self, client_socket):
data = client_socket.recv(1024).decode()
if data == "REQUEST_CHALLENGE":
challenge = self.generate_challenge()
client_socket.send(challenge.encode())
data = client_socket.recv(1024).decode()
username, timestamp, client_hash = data.split(':')
# Fixed: Verify timestamp freshness
request_time = int(timestamp)
if abs(time.time() - request_time) > self.challenge_timeout:
client_socket.send(b"AUTH_FAILED_EXPIRED")
return False
# Fixed: Verify challenge was issued by us and not reused
# (In practice, challenge would be included in the message)
# Recompute expected hash
password = self.get_user_password(username) # Stored securely
# In real implementation, would verify against stored hash
# Fixed: Each authentication is unique due to timestamp and challenge
expected_message = f"{username}:{timestamp}:{self.last_challenge}"
expected_hash = hmac.new(
password.encode(),
expected_message.encode(),
hashlib.sha256
).hexdigest()
if hmac.compare_digest(client_hash, expected_hash):
client_socket.send(b"AUTH_SUCCESS")
return True
client_socket.send(b"AUTH_FAILED")
return False
// Fixed: API authentication with replay protection
import javax.crypto.Mac;
import java.time.Instant;
import java.util.concurrent.ConcurrentHashMap;
public class SecureApiAuth {
private static final long MAX_TIMESTAMP_SKEW = 300; // 5 minutes
private final ConcurrentHashMap<String, Long> usedNonces = new ConcurrentHashMap<>();
public boolean authenticate(HttpServletRequest request) {
String apiKey = request.getHeader("X-API-Key");
String signature = request.getHeader("X-Signature");
String timestamp = request.getHeader("X-Timestamp");
String nonce = request.getHeader("X-Nonce");
// Fixed: Verify timestamp freshness
long requestTime = Long.parseLong(timestamp);
long currentTime = Instant.now().getEpochSecond();
if (Math.abs(currentTime - requestTime) > MAX_TIMESTAMP_SKEW) {
return false; // Request expired
}
// Fixed: Check nonce hasn't been used
String nonceKey = apiKey + ":" + nonce;
Long previousUse = usedNonces.putIfAbsent(nonceKey, currentTime);
if (previousUse != null) {
return false; // Nonce already used - replay attempt!
}
// Clean old nonces periodically
cleanOldNonces();
// Fixed: Signature includes timestamp and nonce
String message = String.format("%s:%s:%s:%s",
timestamp, nonce, request.getMethod(), request.getRequestURI());
String expectedSig = computeHmac(getSecret(apiKey), message);
if (MessageDigest.isEqual(signature.getBytes(), expectedSig.getBytes())) {
return true;
}
return false;
}
private void cleanOldNonces() {
long cutoff = Instant.now().getEpochSecond() - MAX_TIMESTAMP_SKEW * 2;
usedNonces.entrySet().removeIf(entry -> entry.getValue() < cutoff);
}
}
The fix implements challenge-response authentication with timestamps and nonces to prevent replay of captured authentication messages.
Exploited in the Wild
MD5 Hash Replay Attacks (Various Systems, Historical)
CVE-2005-3435 documented MD5 hash authentication vulnerable to replay attacks. Attackers captured hashed credentials and replayed them to gain unauthorized access without knowing the original password.
Cleartext Protocol Replay (Network Applications, Ongoing)
CVE-2007-4961 documented cleartext MD5 transmission combined with replay vulnerability, allowing attackers to capture and replay authentication sequences.
Session Token Replay (Web Applications, Ongoing)
Web applications that don't invalidate session tokens or include freshness guarantees have been exploited through session capture and replay from different locations.
Tools to Test/Exploit
-
Wireshark — Network protocol analyzer for capturing authentication traffic.
-
tcpreplay — Tool for replaying captured network traffic.
-
Burp Suite — Web security tool for capturing and replaying HTTP requests.
CVE Examples
-
CVE-2005-3435 — MD5 hash authentication vulnerable to replay attacks.
-
CVE-2007-4961 — Cleartext MD5 transmission combined with replay vulnerability.
References
-
MITRE Corporation. "CWE-294: Authentication Bypass by Capture-replay." Common Weakness Enumeration. https://cwe.mitre.org/data/definitions/294.html
-
OWASP Foundation. "Session Management Cheat Sheet." https://cheatsheetseries.owasp.org/cheatsheets/Session_Management_Cheat_Sheet.html
-
NIST. "Digital Identity Guidelines: Authentication and Lifecycle Management." SP 800-63B. https://pages.nist.gov/800-63-3/sp800-63b.html