HIGH time of check time of useexpresshmac signatures

Time Of Check Time Of Use in Express with Hmac Signatures

Time Of Check Time Of Use in Express with Hmac Signatures — how this specific combination creates or exposes the vulnerability

Time Of Check Time Of Use (TOCTOU) is a class of race condition where the state of a resource changes between a security check and the subsequent use of that resource. In Express applications that use Hmac Signatures for request authentication, a TOCTOU vulnerability can occur when signature verification and the action protected by that signature are not performed as a single, atomic operation. An attacker can exploit the window between the check and the use by altering the resource or the request parameters after the signature is validated but before the server acts on it.

Consider an endpoint that accepts an Hmac-Signature header, verifies the signature against a shared secret, and then processes a payment or updates a user record. If the server first validates the signature and then reads mutable request data (such as a JSON body or query parameters) to perform the action, an attacker can intercept or mutate that data in flight. Because the signature was computed over the original payload, the server may still consider the request valid, leading to unauthorized operations such as changing the transaction amount or the target user ID. This pattern is common when middleware parses the body after the authentication layer, or when route handlers perform additional lookups based on client-supplied identifiers that were not covered by the Hmac scope.

The vulnerability is exacerbated when the Hmac is computed over only a subset of the request, such as selected headers or a partial URL, while the server uses other unchecked inputs in the critical section. For example, an Hmac might cover the HTTP method, path, and a timestamp, but if the handler later uses a user-controlled ID from the request body to look up and modify a database record, the signature does not protect that ID. An attacker can modify the ID between verification and database update, leading to IDOR or unauthorized data access. Because the signature validation passes, the server treats the request as legitimate, and the race condition is triggered when the mutable state is used.

In distributed or high-concurrency environments, the risk increases as timing variations and asynchronous processing can widen the check-to-use window. An attacker may send many requests with valid Hmac Signatures while concurrently modifying the underlying resource, increasing the likelihood that the server will act on stale or tampered data. The key security principle is to bind the signature to all inputs that will be used in the critical operation and to treat verification and usage as a single, indivisible step to prevent state changes in between.

Hmac Signatures-Specific Remediation in Express — concrete code fixes

To mitigate TOCTOU with Hmac Signatures in Express, ensure that the data used to compute and verify the signature is immutable for the duration of the request and that verification and usage happen atomically. Prefer signing and verifying the entire request payload and all relevant parameters, and avoid additional lookups based on unchecked inputs. Below are concrete code examples demonstrating secure patterns.

Example 1: Verifying Hmac over the full request body and using the data directly

const crypto = require('crypto');
const express = require('express');
const app = express();

app.use(express.json());

const SHARED_SECRET = process.env.HMAC_SECRET;

function verifyHmac(req, res, next) {
  const signature = req.headers['x-hmac-signature'];
  if (!signature) {
    return res.status(401).json({ error: 'Missing signature' });
  }
  const payload = JSON.stringify(req.body);
  const expected = crypto
    .createHmac('sha256', SHARED_SECRET)
    .update(payload)
    .digest('hex');
  if (!crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))) {
    return res.status(401).json({ error: 'Invalid signature' });
  }
  next();
}

app.post('/transfer', verifyHmac, (req, res) => {
  // Use req.body directly after verification; no additional ID lookup from client
  const { fromAccount, toAccount, amount } = req.body;
  if (!fromAccount || !toAccount || typeof amount !== 'number' || amount <= 0) {
    return res.status(400).json({ error: 'Invalid payload' });
  }
  // Perform the transfer using only the signed body fields
  // ...
  res.json({ status: 'ok' });
});

Example 2: Including critical identifiers in the Hmac scope

const crypto = require('crypto');
const express = require('express');
const app = express();
app.use(express.json());

const SHARED_SECRET = process.env.HMAC_SECRET;

app.post('/resource/:id', (req, res, next) => {
  // Include path parameter and body in the signature verification
  const payload = JSON.stringify({
    pathId: req.params.id,
    body: req.body
  });
  const expected = crypto
    .createHmac('sha256', SHARED_SECRET)
    .update(payload)
    .digest('hex');
  const signature = req.headers['x-hmac-signature'];
  if (!signature || !crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))) {
    return res.status(401).json({ error: 'Invalid signature' });
  }
  next();
}, (req, res) => {
  // Now safe to use req.params.id and req.body knowing they were signed
  const { action } = req.body;
  // ...
  res.json({ status: 'ok' });
});

Best practices summary

  • Compute the Hmac over all inputs that will be used in the critical section, including path parameters, selected headers, and the request body.
  • Perform verification and the sensitive operation in the same handler or middleware chain without intervening lookups based on mutable data.
  • Use crypto.timingSafeEqual to compare signatures to prevent timing attacks on the MAC.
  • Avoid allowing the client to dictate identifiers that are used for database operations after signature verification; if necessary, map signed identifiers to internal IDs server-side within the same atomic step.

Frequently Asked Questions

Can TOCTOU with Hmac Signatures be exploited if the request body is encrypted?
Encryption protects confidentiality but does not prevent TOCTOU. An attacker can still mutate unencrypted metadata or parameters outside the encrypted portion, or the server may decrypt and then use unchecked values. Always include all mutable data used in the operation within the Hmac scope and treat verification and use atomically.
Does middleBrick detect insecure Hmac usage patterns that may lead to TOCTOU?
middleBrick scans unauthenticated attack surfaces and checks input validation and authentication controls. It can surface findings related to weak or inconsistent Hmac usage and missing integrity checks, mapping them to relevant standards such as OWASP API Top 10. Use the CLI or Web Dashboard to review detailed recommendations and prioritize fixes.