HIGH replay attackapi keys

Replay Attack with Api Keys

How Replay Attack Manifests in API Keys

Replay attacks in API keys occur when an attacker intercepts a valid API key and its associated request, then resubmits that same request to the server at a later time. Unlike cryptographic replay attacks that target encrypted sessions, API key replay attacks exploit the stateless nature of REST APIs where the same key and payload can be reused repeatedly.

The most common API key replay scenario involves intercepting an API key from network traffic, logs, or client-side code. Since API keys often remain valid for extended periods (sometimes indefinitely), an attacker who captures a key can replay any request that uses it. This becomes particularly dangerous when the intercepted request includes privileged operations like account modifications, financial transactions, or data exports.

Consider this vulnerable pattern in Node.js:

// Vulnerable: API key never expires and requests are idempotent
app.post('/transfer', (req, res) => {
const apiKey = req.headers['x-api-key'];
const { from, to, amount } = req.body;

// No replay protection - same request can be resent
transferFunds(apiKey, from, to, amount);
res.json({ success: true });
});

An attacker who captures this request can repeatedly submit it to drain the account. The problem compounds when APIs use predictable request structures or when API keys are embedded in client-side JavaScript, making them trivial to extract.

Mobile applications often ship with hardcoded API keys, creating massive replay attack surfaces. If a banking app contains an API key that authorizes fund transfers, decompiling the APK reveals the key, allowing attackers to craft and replay transfer requests at will.

Time-sensitive operations without proper nonce validation are especially vulnerable. A password reset request using only an API key and email address can be replayed to repeatedly trigger reset emails, enabling credential stuffing attacks or denial of service against user accounts.

API Keys-Specific Detection

Detecting replay attack vulnerabilities in API keys requires examining both the key lifecycle and request handling patterns. Start by analyzing how API keys are generated, stored, and validated.

Key characteristics that indicate replay vulnerability:

  • API keys with unlimited or very long validity periods (90+ days)
  • Lack of key rotation mechanisms
  • No request timestamp validation
  • Idempotent operations without nonce validation
  • middleBrick's API security scanner specifically tests for replay attack vulnerabilities by:

    • Analyzing key expiration policies in OpenAPI specifications
    • Testing whether intercepted requests can be successfully replayed
    • Checking for proper timestamp validation in request headers
    • Verifying nonce or request ID validation mechanisms

    Manual detection should include:

    const testReplayVulnerability = async (baseUrl, apiKey) => {
    const initialResponse = await fetch(`${baseUrl}/sensitive-endpoint`, {
    headers: { 'Authorization': `Bearer ${apiKey}` }
    });

    // Wait and replay the same request
    await new Promise(resolve => setTimeout(resolve, 1000));

    const replayedResponse = await fetch(`${baseUrl}/sensitive-endpoint`, {
    headers: { 'Authorization': `Bearer ${apiKey}` }
    });

    return {
    initialStatus: initialResponse.status,
    replayedStatus: replayedResponse.status,
    vulnerable: initialResponse.status === 200 && replayedResponse.status === 200
    };
    };

    Network-level detection involves monitoring for repeated identical requests from the same API key within short timeframes. Tools like Wireshark or mitmproxy can capture traffic to verify whether requests contain sufficient entropy to prevent replay.

    Log analysis often reveals replay attempts through patterns of repeated identical API calls. Look for bursts of identical requests with the same API key, especially those that modify state or access sensitive resources.

API Keys-Specific Remediation

Effective replay attack prevention for API keys requires a multi-layered approach combining key lifecycle management, request validation, and operational controls.

Key Expiration and Rotation

Implement short-lived API keys with automatic rotation:

// JWT-based API key with 15-minute expiration
const generateSecureApiKey = (userId) => {
return jwt.sign(
{ userId, type: 'api_key', issuedAt: new Date().toISOString() },
process.env.API_SECRET,
{ expiresIn: '15m' }
);
};

Store keys in a database with metadata tracking issuance and rotation schedules:

CREATE TABLE api_keys (
id UUID PRIMARY KEY,
user_id UUID NOT NULL,
key_hash TEXT NOT NULL,
created_at TIMESTAMP NOT NULL,
expires_at TIMESTAMP NOT NULL,
last_used_at TIMESTAMP,
rotation_policy TEXT NOT NULL
);

Request Timestamp Validation

Reject requests with timestamps outside acceptable windows:

app.use((req, res, next) => {
const timestamp = req.headers['x-request-timestamp'];
const requestTime = new Date(timestamp).getTime();

// Reject if request is older than 5 minutes
if (now - requestTime > 5 * 60 * 1000) {
return res.status(400).json({ error: 'Request timestamp too old' });
}
next();
});

Nonce and Request ID Validation

Require unique nonces for state-changing operations:

app.post('/transfer', async (req, res) => {
const { apiKey, nonce, from, to, amount } = req.body;

// Check if nonce already used
const used = await db.collection('nonces').findOne({ nonce });
if (used) {
return res.status(400).json({ error: 'Nonce already used' });
}

// Process transfer
await processTransfer(apiKey, from, to, amount);

// Mark nonce as used
await db.collection('nonces').insertOne({ nonce, usedAt: new Date() });
res.json({ success: true });
});

Rate Limiting and Behavioral Analysis

Implement intelligent rate limiting that considers API key patterns:

const rateLimiter = new RateLimiterRedis({
store: new Redis({ host: 'redis-server' }),
keyGenerator: (req) => req.headers['x-api-key'] || req.ip,
points: 100, // 100 requests
duration: 60 // per minute
});

For high-security operations, implement challenge-response mechanisms that change with each request, making replay attacks computationally expensive.

Frequently Asked Questions

Can JWT tokens be replayed if intercepted?
Yes, standard JWT tokens can be replayed if intercepted, which is why they should include short expiration times (typically 5-15 minutes) and be combined with additional protections like request timestamps and nonces. middleBrick's scanner specifically tests JWT implementations for replay vulnerabilities by attempting to reuse captured tokens.
How does middleBrick detect replay attack vulnerabilities?
middleBrick detects replay vulnerabilities by analyzing API key expiration policies in specifications, testing whether intercepted requests can be successfully replayed, and checking for proper timestamp and nonce validation. The scanner runs 12 parallel security checks including replay attack detection, providing a security score and prioritized findings with remediation guidance.