HIGH request smugglingexpresshmac signatures

Request Smuggling in Express with Hmac Signatures

Request Smuggling in Express with Hmac Signatures — how this specific combination creates or exposes the vulnerability

Request smuggling occurs when an application processes HTTP requests differently depending on whether they are interpreted as front-end (e.g., a load balancer or proxy) or back-end (e.g., Express). When Hmac Signatures are used for request authentication but the application does not canonicalize the exact byte sequence used to verify the signature, smuggling becomes possible. The attacker crafts two requests that diverge in how headers or body are parsed by the front-end versus Express, while producing the same Hmac signature for the trusted representation.

In Express, if you compute the Hmac over a subset of headers or a transformed body (e.g., lowercasing header names or normalizing JSON whitespace) but the front-end computes it over the raw request, the front-end may accept a request as valid while Express interprets it differently. For example, a front-end might forward X-Original-URI while Express uses req.url; if the signature is computed without the full path or with a different ordering of query parameters, smuggling can bypass intended routing and authorization checks.

A concrete scenario: an API uses Hmac signatures in headers (X-Signature) and includes a timestamp and a canonical string such as HTTP_METHOD PATH TIMESTAMP BODY_SHA256. If the front-end appends an extra header (like X-Forwarded-Host) that Express ignores when recomputing the canonical string, the signature still matches to the front-end but Express may route the request to a different endpoint or interpret content-length discrepancies differently. This discrepancy enables request smuggling variants such as CL.TE (Content-Length vs. Transfer-Encoding), where the attacker sends Content-Length: 0 and a separate Transfer-Encoding: chunked body. The front-end processes one message length, while Express parses another, allowing a second malicious request to be smuggled in and executed with the same Hmac context.

Because middleBrick tests unauthenticated attack surfaces and includes HTTP protocol-level checks, it can surface inconsistencies between how front-end and back-end interpret requests and signatures. Findings may highlight missing canonicalization, inconsistent header usage, or missing validation of message framing that enable smuggling. The scanner does not fix the implementation but provides prioritized findings with remediation guidance to align signature computation and request parsing across layers.

Hmac Signatures-Specific Remediation in Express — concrete code fixes

Remediation centers on ensuring the exact byte sequence used to compute and verify Hmac is identical across all layers that handle the request. In Express, canonicalize the method, path, selected headers, timestamp, and body before signing and verification. Use a stable header serialization order, avoid including hop-by-hop or proxy-specific headers in the signature base string, and enforce strict message framing so front-end and back-end agree on Content-Length and Transfer-Encoding handling.

Example: canonical string construction and verification in Express using Node.js crypto.

const crypto = require('crypto');

function buildCanonicalString(req) {
  const method = req.method.toUpperCase();
  const path = req.path; // use req.path, not req.url, to avoid query string ambiguities
  const timestamp = req.headers['x-timestamp'];
  const bodySha256 = crypto.createHash('sha256').update(req.rawBody || '').digest('hex');
  const headers = ['x-request-id', 'x-timestamp', 'content-type'].map(h => h.toLowerCase()).sort().map(h => {
    return h + ':' + req.headers[h];
  }).join('\n');
  return [method, path, timestamp, bodySha256, headers].join('\n');
}

function verifySignature(req, secret) {
  const expected = buildCanonicalString(req);
  const signature = req.headers['x-signature'];
  const actual = crypto.createHmac('sha256', secret).update(expected).digest('hex');
  return crypto.timingSafeEqual(Buffer.from(actual), Buffer.from(signature));
}

app.use((req, res, next) => {
  // Ensure rawBody is available (e.g., via a body parser that preserves bytes)
  if (!verifySignature(req, process.env.HMAC_SECRET)) {
    return res.status(401).json({ error: 'invalid_signature' });
  }
  next();
});

Example: Express route using the verification middleware and ensuring consistent body handling.

app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
  // req.body is a Buffer; convert for business logic after verification
  const bodyObj = JSON.parse(req.body.toString('utf8'));
  // process bodyObj
  res.json({ received: true });
});

Additional measures: explicitly set Content-Length and avoid chunked transfer encoding when operating across layers with different parsing behavior; reject requests with both Content-Length and Transfer-Encoding (CL.TE mitigation); normalize header names to lowercase and sort them deterministically; include a request ID and timestamp in the canonical string to prevent replay; and use a stable separator (e.g., newline) that cannot appear in header values without proper escaping. These steps reduce the risk that front-end and back-end interpretations diverge, limiting opportunities for request smuggling while preserving the integrity of Hmac-based authentication.

Frequently Asked Questions

Why does Hmac signature canonicalization matter for request smuggling in Express?
If the canonical string used to compute or verify the Hmac differs between layers (e.g., front-end vs Express), one layer may accept a request while the other interprets it differently. This mismatch can enable request smuggling, where a carefully crafted request is processed differently by the proxy and the application, bypassing intended security or routing controls.
Can middleBrick detect Hmac-related request smuggling issues?
middleBrick scans unauthenticated attack surfaces and includes HTTP protocol-level checks. It can surface inconsistencies in how requests are interpreted and highlight missing canonicalization or inconsistent header usage that may enable smuggling, providing prioritized findings and remediation guidance.