TL;DR
Replay attacks happen when someone intercepts a valid instruction sent over SSL and re-sends it later to cause unwanted actions. This guide shows how to protect against them using nonces, timestamps, and sequence numbers.
Protecting Against Replay Attacks Over SSL
- Understand the Problem: A replay attack involves capturing a legitimate SSL-encrypted message (e.g., an instruction to transfer funds) and resending it without authorization. Because SSL provides confidentiality but not necessarily integrity or freshness, the server might process the same instruction multiple times.
- Implement Nonces:
- A nonce (number used once) is a random value generated by the client for each request.
- The server keeps track of recently used nonces. If it receives a request with a previously seen nonce, it rejects it.
- Client-Side: Generate a unique nonce before sending each instruction.
import uuid nonce = str(uuid.uuid4()) - Server-Side (Python example): Store nonces in a database or cache with an expiry time.
import time nonces = {} expiry_time = 60 # seconds def check_nonce(nonce): if nonce in nonces and time.time() - nonces[nonce] < expiry_time: return False # Replay attack detected else: nonces[nonce] = time.time() return True
- Use Timestamps:
- Include a timestamp in each request, indicating when the instruction was sent.
- The server checks if the timestamp is within an acceptable window (e.g., +/- 5 minutes). Requests with timestamps outside this window are rejected.
- Client-Side: Get current time before sending.
import datetime timestamp = datetime.datetime.now().isoformat() - Server-Side (Python example): Validate the timestamp.
import datetime acceptable_skew = 300 # seconds def check_timestamp(timestamp): try: dt = datetime.datetime.fromisoformat(timestamp) now = datetime.datetime.now() if abs((now - dt).total_seconds()) > acceptable_skew: return False # Timestamp too old or future return True except ValueError: return False # Invalid timestamp format
- Employ Sequence Numbers:
- The client includes a monotonically increasing sequence number in each request.
- The server verifies that the sequence numbers are consecutive and rejects requests with out-of-order or duplicate numbers.
- Client-Side: Increment sequence number for each request.
sequence_number = 0 def get_next_sequence_number(): global sequence_number sequence_number += 1 return sequence_number - Server-Side (Python example): Track the last seen sequence number for each client.
last_seen_sequences = {} def check_sequence_number(client_id, sequence_number): if client_id not in last_seen_sequences: last_seen_sequences[client_id] = 0 if sequence_number >= last_seen_sequences[client_id] + 1: last_seen_sequences[client_id] = sequence_number return True else: return False # Duplicate or out-of-order sequence number
- Combine Techniques: For the strongest protection, use a combination of nonces, timestamps, and sequence numbers. This makes it significantly harder for an attacker to successfully replay instructions.
- SSL/TLS Configuration: Ensure your SSL/TLS configuration is up-to-date with strong ciphers and protocols (e.g., TLS 1.3). While this doesn’t directly prevent replay attacks, it strengthens the overall security of the connection.
- Mutual Authentication: Consider using mutual authentication where both client and server verify each other’s identities. This adds another layer of security.

