HIGH time of check time of usehmac signatures

Time Of Check Time Of Use with Hmac Signatures

How Time Of Check Time Of Use Manifests in Hmac Signatures

Time Of Check Time Of Use (TOCTOU) vulnerabilities in HMAC signatures occur when the timestamp or other time-sensitive data used for validation is checked at one point in time but the signature itself is verified at a later point. This race condition can allow attackers to bypass HMAC-based authentication by manipulating the timing between these operations.

In HMAC-based API authentication, the typical flow involves checking a timestamp to ensure the request isn't stale, then verifying the HMAC signature. The critical flaw emerges when these two operations aren't atomic. An attacker can exploit this by intercepting a valid request, modifying it slightly, and resubmitting it during the window between the timestamp check and signature verification.

// Vulnerable TOCTOU pattern in HMAC authentication
function verifyRequest(req) {
    // Time check (TO)
    const timestamp = parseInt(req.headers['x-timestamp']);
    if (Math.abs(Date.now() - timestamp) > 300000) { // 5 minute window
        return false;
    }
    
    // Signature verification (TU) - happens separately
    const expected = generateHmac(req.body, secret);
    return hmacEquals(req.headers['x-signature'], expected);
}

The vulnerability lies in the fact that the timestamp check and HMAC verification happen as separate operations. An attacker can capture a valid request, wait until the timestamp is about to expire, then rapidly replay it multiple times. The first check passes (timestamp is valid), but by the time verification occurs, the request has technically expired.

Another TOCTOU scenario in HMAC signatures involves nonce validation. When a server checks if a nonce has been used before allowing signature verification, there's a window where the nonce could be marked as unused, the check passes, but then another request simultaneously marks it as used before verification completes.

// TOCTOU in nonce-based HMAC validation
function verifyWithNonce(req) {
    const nonce = req.headers['x-nonce'];
    
    // TO: Check if nonce exists
    if (nonceDatabase.exists(nonce)) {
        return false; // nonce already used
    }
    
    // Critical TOCTOU window: between check and verification
    const expected = generateHmac(req.body, secret);
    if (!hmacEquals(req.headers['x-signature'], expected)) {
        return false;
    }
    
    // TU: Mark nonce as used (but too late)
    nonceDatabase.markUsed(nonce);
    
    return true;
}

This pattern is particularly dangerous in distributed systems where nonce validation might involve network calls or database transactions that introduce additional timing variations. The attacker's goal is to force the system into a state where the nonce appears unused during the check but becomes used during verification, potentially causing inconsistent behavior or denial of service.

HMAC Signatures-Specific Detection

Detecting TOCTOU vulnerabilities in HMAC implementations requires both static analysis and dynamic testing. Static analysis looks for patterns where timestamp validation and signature verification are separate operations, while dynamic testing attempts to exploit the race condition.

Key indicators of TOCTOU vulnerabilities in HMAC code:

  • Separate timestamp validation and signature verification functions
  • Non-atomic nonce validation patterns
  • Use of mutable shared state between validation steps
  • Lack of transactional integrity in verification processes
  • Multiple network/database calls between validation steps

middleBrick's HMAC-specific scanning identifies these patterns through black-box testing. The scanner sends requests with carefully crafted timing variations to detect if the server's validation logic is vulnerable to TOCTOU attacks.

// middleBrick-style HMAC TOCTOU detection
function detectToctouHmac(url) {
    const secret = 'test-secret';
    const body = JSON.stringify({ test: 'data' });
    const timestamp = Date.now();
    
    // Generate valid HMAC
    const validSig = generateHmac(body, secret);
    
    // Send initial request to establish baseline
    const initial = sendRequest(url, {
        headers: {
            'x-timestamp': timestamp,
            'x-signature': validSig
        },
        body: body
    });
    
    // TOCTOU attack simulation: rapid replay with timing manipulation
    const results = [];
    for (let i = 0; i < 10; i++) {
        const delayed = sendRequest(url, {
            headers: {
                'x-timestamp': timestamp - 290000, // near expiration
                'x-signature': validSig
            },
            body: body
        });
        results.push(delayed.status);
    }
    
    // Analyze for inconsistent responses
    const inconsistent = results.some(status => status !== initial.status);
    return inconsistent ? 'TOCTOU_VULNERABLE' : 'SECURE';
}

middleBrick's HMAC scanning also examines the cryptographic implementation for weak comparison functions. Using standard equality operators (== or ===) instead of constant-time comparison functions can leak timing information, making the TOCTOU window even more exploitable.

The scanner tests for nonce-related TOCTOU by sending concurrent requests with the same nonce and analyzing the server's response consistency. If the server sometimes accepts and sometimes rejects identical requests, it indicates a race condition in the nonce validation logic.

HMAC Signatures-Specific Remediation

Fixing TOCTOU vulnerabilities in HMAC implementations requires making the validation process atomic and eliminating the window between check and use. The most effective approach is to combine timestamp validation and signature verification into a single atomic operation.

// Secure HMAC validation with atomic operations
function verifyRequestAtomic(req) {
    const timestamp = parseInt(req.headers['x-timestamp']);
    const signature = req.headers['x-signature'];
    const body = req.body;
    
    // Single atomic validation step
    const now = Date.now();
    const timeValid = Math.abs(now - timestamp) <= 300000;
    
    // Generate expected HMAC with timestamp included in the data
    const dataToSign = body + '|' + timestamp;
    const expected = generateHmac(dataToSign, secret);
    
    // Constant-time comparison
    const sigValid = hmacEquals(signature, expected);
    
    // Both checks must pass atomically
    return timeValid && sigValid;
}

// Constant-time comparison function
function hmacEquals(a, b) {
    if (a.length !== b.length) return false;
    let result = 0;
    for (let i = 0; i < a.length; i++) {
        result |= a.charCodeAt(i) ^ b.charCodeAt(i);
    }
    return result === 0;
}

This atomic approach ensures that both the timestamp and signature are validated together, eliminating the TOCTOU window. The timestamp is included in the data that gets signed, so any attempt to modify it would invalidate the HMAC.

For nonce-based HMAC systems, use database transactions or atomic operations to ensure nonce validation and marking are indivisible:

// Secure nonce validation with atomic database operations
function verifyWithAtomicNonce(req) {
    const nonce = req.headers['x-nonce'];
    const body = req.body;
    
    // Atomic database operation: check and mark in single transaction
    const result = db.transaction(() => {
        // Attempt to claim the nonce (returns false if already claimed)
        const success = nonceDatabase.claimNonce(nonce);
        if (!success) {
            return false;
        }
        
        // Verify signature (only if nonce claim succeeded)
        const expected = generateHmac(body, secret);
        return hmacEquals(req.headers['x-signature'], expected);
    });
    
    return result;
}

// Database-level atomic nonce claim
class NonceDatabase {
    claimNonce(nonce) {
        // Atomic check-and-set operation
        return db.query(`
            UPDATE nonces 
            SET claimed = true, claimed_at = NOW()
            WHERE nonce = $1 AND claimed = false
            RETURNING claimed
        `, [nonce]).then(result => result.rowCount > 0);
    }
}

This pattern ensures that nonce validation and state mutation happen as a single atomic operation, preventing any TOCTOU window where the nonce could be claimed by multiple requests simultaneously.

Another critical remediation is implementing proper clock synchronization. TOCTOU vulnerabilities are exacerbated when servers have unsynchronized clocks. Use NTP or similar protocols to ensure all servers have consistent timestamps, and consider using server-side timestamp generation rather than client-provided timestamps.

// Server-generated timestamps for HMAC
function generateSecureRequest(body, secret) {
    const serverTimestamp = Date.now();
    const dataToSign = body + '|' + serverTimestamp;
    const signature = generateHmac(dataToSign, secret);
    
    return {
        body: body,
        headers: {
            'x-timestamp': serverTimestamp,
            'x-signature': signature
        }
    };
}

// Server verifies using its own timestamp generation
function verifyServerGenerated(req) {
    const serverTimestamp = Date.now();
    const body = req.body;
    const dataToSign = body + '|' + req.headers['x-timestamp'];
    const expected = generateHmac(dataToSign, secret);
    
    // Verify both signature AND that client timestamp is close to server time
    return hmacEquals(req.headers['x-signature'], expected) &&
           Math.abs(serverTimestamp - parseInt(req.headers['x-timestamp'])) < 300000;
}

By generating timestamps server-side, you eliminate the client's ability to manipulate timing, significantly reducing the TOCTOU attack surface in HMAC-based authentication systems.

Frequently Asked Questions

How can I test my HMAC implementation for TOCTOU vulnerabilities?
Use middleBrick's CLI tool to scan your API endpoints. The scanner automatically tests for TOCTOU vulnerabilities by sending requests with manipulated timing and analyzing response inconsistencies. You can also manually test by capturing valid requests and rapidly replaying them with slight timing variations to see if the server inconsistently accepts or rejects them.
Does TOCTOU only affect HMAC signatures, or are other authentication methods vulnerable too?
TOCTOU affects any authentication mechanism that performs multiple time-separated validation steps. JWT tokens, API keys, session-based authentication, and even database access controls can all be vulnerable if they check permissions or validity at one point but enforce them at another. HMAC signatures are particularly susceptible because they often combine timestamp validation with cryptographic verification.