HIGH Authentication & Authorization

Replay Attack in APIs

What is Replay Attack?

A replay attack occurs when an attacker intercepts a valid API request and maliciously retransmits it to the server, tricking the system into performing an unintended action. Unlike man-in-the-middle attacks that modify data in transit, replay attacks exploit the fact that many APIs accept requests without validating whether they're being sent at the appropriate time or context.

The vulnerability stems from APIs that rely solely on authentication without proper replay protection mechanisms. An attacker who captures a legitimate request—through network sniffing, compromised endpoints, or other means—can simply resend that same request to achieve the same effect. This is particularly dangerous for APIs handling financial transactions, authentication flows, or state-changing operations.

Replay attacks exploit a fundamental weakness in stateless API design: if an API doesn't track request freshness or context, any captured request remains valid indefinitely. The attacker doesn't need to understand the API's internal logic—they just need to resend what worked before.

How Replay Attack Affects APIs

Replay attacks can have devastating consequences across multiple API scenarios. In financial APIs, an attacker could intercept a money transfer request and replay it repeatedly, draining accounts or creating unauthorized duplicate transactions. For authentication APIs, captured login requests or session tokens could grant unauthorized access to protected resources.

Consider a banking API that processes transfers with this endpoint:

POST /api/transfer
{
  "from_account": "123456",
  "to_account": "789012",
  "amount": 1000.00
}

If an attacker captures this request, they could replay it multiple times, causing multiple unauthorized transfers. The server has no way to know these are duplicate requests rather than legitimate ones.

Another common scenario involves API keys or tokens. If an API authenticates requests using only static credentials without additional context, any captured request remains valid. This extends to webhook endpoints, where replayed requests could trigger duplicate payments, notifications, or data processing.

APIs without proper replay protection are essentially vulnerable to any request they've ever accepted being reused maliciously, potentially leading to data breaches, financial losses, or service disruption.

How to Detect Replay Attack

Detecting replay attack vulnerabilities requires examining how your API handles request uniqueness and timing. Look for APIs that accept requests without nonce values, timestamps, or sequence numbers. Check if your API validates that requests are being processed in the correct order and within expected time windows.

middleBrick's replay attack detection examines several critical factors. The scanner tests whether your API properly validates request freshness by attempting to replay captured requests with slight modifications. It checks for the presence of anti-replay mechanisms like timestamps, nonces, or sequence numbers in your API's authentication and request handling.

The scanner also evaluates whether your API properly handles duplicate requests. Many APIs should implement idempotency keys—unique identifiers that allow safe retry of requests without unintended side effects. middleBrick tests whether your API can distinguish between legitimate retries and malicious replays.

For APIs handling sensitive operations, middleBrick checks whether proper replay protection is implemented at the protocol level. This includes examining whether your API uses HTTPS exclusively (preventing network-level interception) and whether it implements appropriate session management that doesn't allow captured session data to be reused indefinitely.

The scanner's findings include specific recommendations for implementing replay protection based on your API's architecture and use case, helping you understand exactly where your API is vulnerable to request replay attacks.

Prevention & Remediation

Preventing replay attacks requires implementing multiple layers of protection. The most fundamental approach is using nonces—numbers used once—that your API generates and validates for each request. Here's a practical implementation:

import uuid
import time
from datetime import datetime, timedelta

# Server-side nonce store (in production, use Redis or database)
once_store = {}

class ReplayProtection:
    @staticmethod
    def generate_nonce():
        return str(uuid.uuid4())
    
    @staticmethod
    def validate_nonce(nonce, timeout_seconds=300):
        if nonce in nonce_store:
            # Check if nonce is still within valid timeframe
            timestamp = nonce_store[nonce]
            if datetime.now() - timestamp < timedelta(seconds=timeout_seconds):
                return False  # Replay detected
            else:
                del nonce_store[nonce]  # Old nonce, remove it
        
        # Store new nonce with current timestamp
        nonce_store[nonce] = datetime.now()
        return True

# API endpoint example
def transfer_funds(request):
    nonce = request.headers.get('X-Nonce')
    if not ReplayProtection.validate_nonce(nonce):
        return {'error': 'Invalid or replayed request'}, 403
    
    # Process transfer only if nonce is valid
    process_transfer(request.json)
    return {'status': 'success'}, 200

Another effective approach is implementing timestamps with tolerance windows. Your API should reject requests that are too old or too far in the future:

def validate_timestamp(request_time, tolerance_seconds=300):
    current_time = int(time.time())
    if abs(current_time - request_time) > tolerance_seconds:
        return False
    return True

# Include timestamp in API requests
{
  "timestamp": 1703456789,
  "data": {...}
}

For APIs requiring strong replay protection, consider implementing HMAC signatures with timestamps and nonces. This ensures both integrity and freshness:

import hmac, hashlib

def generate_signature(secret_key, message, nonce, timestamp):
    msg = f"{message}{nonce}{timestamp}".encode()
    return hmac.new(secret_key.encode(), msg, hashlib.sha256).hexdigest()

def verify_signature(request, secret_key):
    signature = request.headers['X-Signature']
    expected = generate_signature(
        secret_key,
        request.json['data'],
        request.headers['X-Nonce'],
        request.headers['X-Timestamp']
    )
    return hmac.compare_digest(signature, expected)

Finally, implement proper idempotency for operations that can be retried safely. Use idempotency keys that your API can check to prevent duplicate processing:

def process_payment(request):
    idempotency_key = request.headers.get('Idempotency-Key')
    existing = check_existing_operation(idempotency_key)
    if existing:
        return existing  # Return previous result
    
    result = execute_payment(request.json)
    store_operation_result(idempotency_key, result)
    return result

Real-World Impact

Replay attacks have caused significant real-world damage. In 2018, a major cryptocurrency exchange suffered a replay attack that allowed attackers to duplicate transactions across different blockchain networks, resulting in millions of dollars in losses. The vulnerability existed because the exchange didn't properly implement replay protection when transactions were broadcast across multiple networks.

The 2016 SWIFT banking system attacks demonstrated how replay vulnerabilities can affect traditional financial infrastructure. Attackers captured valid SWIFT messages and replayed them to move millions of dollars between accounts. The lack of proper message sequencing and replay detection in certain SWIFT implementations enabled these attacks.

Mobile banking apps have also been targets. In several incidents, attackers intercepted API requests from banking applications and replayed them to perform unauthorized transactions. These attacks were possible because the apps relied solely on user authentication without implementing request-level replay protection.

Even modern web applications aren't immune. OAuth 1.0 implementations that didn't properly handle nonce validation were vulnerable to replay attacks, allowing attackers to capture and reuse authentication tokens. This led to the development of OAuth 2.0 with improved security measures against replay attacks.

The common thread in these incidents is that replay attacks exploit fundamental design oversights rather than sophisticated vulnerabilities. They're preventable with proper implementation of timestamp validation, nonces, and request uniqueness checks—yet they continue to affect systems that overlook these basic security measures.

Frequently Asked Questions

What's the difference between replay attack and man-in-the-middle attack?
A man-in-the-middle attack involves intercepting and potentially modifying messages between two parties, while a replay attack simply captures and retransmits a valid message without modification. Replay attacks don't require the attacker to understand or alter the message content—they just need to resend what worked before. Man-in-the-middle attacks are often more sophisticated, while replay attacks exploit simpler design flaws in request validation.
Can replay attacks be performed over HTTPS?
Yes, HTTPS prevents network-level interception but doesn't protect against replay attacks if an attacker gains access to captured requests through other means. This could happen through compromised endpoints, insider threats, or if the attacker has access to the client device where requests are stored. HTTPS is necessary but not sufficient for preventing replay attacks—you still need proper request validation mechanisms.
How does middleBrick detect replay attack vulnerabilities?
middleBrick tests your API's resistance to replay by attempting to resend captured requests with slight modifications to check if the API properly validates request freshness. The scanner examines whether your API uses nonces, timestamps, or other anti-replay mechanisms, and whether it can distinguish between legitimate retries and malicious replays. It also checks for proper handling of duplicate requests and evaluates whether your API implements appropriate idempotency for operations that can be safely retried.