HIGH dangling dnsexpresshmac signatures

Dangling Dns in Express with Hmac Signatures

Dangling Dns in Express with Hmac Signatures — how this specific combination creates or exposes the vulnerability

A dangling DNS configuration in an Express application that uses HMAC signatures for request validation can expose a subtle but serious security risk. In this setup, the server typically computes an HMAC over selected parts of an incoming request—such as the raw path, selected headers, and a timestamp—and verifies the signature sent by the client. If the hostname or domain used in the request can be controlled in a way that leads to a DNS resolution chain pointing outside the intended service boundary, an attacker may be able to influence which IP the application ultimately reaches after a redirect or during an SSRF-related flow.

Consider an Express route that validates an HMAC but then performs an HTTP request to a host derived from a client-supplied parameter. When that parameter resolves through DNS, a dangling CNAME or an unresolvable hostname can cause resolution to an internal or external host that was not intended. Because the HMAC was computed over the original hostname, an attacker who can poison or influence DNS (for example through a vulnerable third‑party service or a misconfigured internal resolver) may be able to make the request appear legitimate while reaching a different backend. The server-side HMAC check does not protect against this class of confusion because the signature is tied to the original, attacker‑controlled hostname rather than to the final resolved destination used for outbound requests.

In practice, this combination shows up during scans as a BOLA/IDOR–adjacent confusion and as an SSRF indicator when outbound HTTP clients follow redirects or use the supplied hostname. middleBrick detects this pattern during its parallel checks: the unauthenticated attack surface is exercised, the OpenAPI/Swagger spec is analyzed with full $ref resolution, and runtime behavior is compared against the declared authentication and authorization model. Without binding the HMAC to the resolved endpoint or enforcing strict hostname pinning, the application remains vulnerable to confusion attacks and data exposure even though the signature itself is correctly formed.

To illustrate, an Express route that computes an HMAC over the URL path and a timestamp, then forwards the request to a host derived from user input, can be misled if the input hostname later resolves unexpectedly. The detection highlights the need to validate not only the signature but also the final network destination and to treat DNS as an attacker‑controlled factor.

Hmac Signatures-Specific Remediation in Express — concrete code fixes

Mitigating risks around dangling DNS when using HMAC signatures in Express requires both cryptographic hygiene and strict network controls. The core idea is to ensure that the data used to compute and verify the HMAC includes elements that cannot be altered by DNS or client manipulation, and that outbound requests do not blindly follow user‑supplied hostnames.

First, bind the HMAC to a canonical representation of the target endpoint. Instead of including only the path and timestamp, include a fixed service identifier and a validated hostname or IP that is resolved server‑side. Do not allow the client to dictate the final destination used for outbound calls. Use a strict allowlist of destinations and resolve hostnames once at startup or via a controlled internal resolver.

Second, avoid following redirects or forwarding requests to hosts derived from client input. If you must call another service, resolve the hostname to a concrete IP at configuration time and pin it (for example by verifying certificate SANs or using mTLS). This prevents DNS hijacking from redirecting your outbound traffic without invalidating the HMAC, because the HMAC was computed with the intended canonical target.

Below are concrete Express code examples that demonstrate a safer pattern. The first example shows HMAC generation and verification with explicit hostname binding, and the second shows a controlled outbound call that does not rely on user‑supplied DNS resolution at request time.

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

const SHARED_SECRET = process.env.SHARED_SECRET; // store securely
const ALLOWED_SERVICE_HOST = 'api.example.com'; // canonical, server‑side defined host
const ALLOWED_SERVICE_PORT = 443;

function computeHmac(payload) {
  return crypto.createHmac('sha256', SHARED_SECRET)
    .update(payload)
    .digest('hex');
}

function verifyHmac(payload, receivedSignature) {
  const expected = computeHmac(payload);
  return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(receivedSignature));
}

const app = express();
app.use(express.json({ type: 'application/json' }));

// Example endpoint that validates HMAC and makes a controlled outbound call
app.post('/webhook', (req, res) => {
  const receivedSignature = req.get('X-Signature');
  const timestamp = req.get('X-Timestamp');
  const nonce = req.get('X-Nonce');

  if (!receivedSignature || !timestamp || !nonce) {
    return res.status(400).send('Missing security headers');
  }

  // Build the exact string that was signed by the client
  const payload = `POST:/webhook\n${timestamp}\n${nonce}`;

  if (!verifyHmac(payload, receivedSignature)) {
    return res.status(401).send('Invalid signature');
  }

  // At this point the request is authenticated; proceed with safe outbound call
  const safeUrl = `https://${ALLOWED_SERVICE_HOST}:${ALLOWED_SERVICE_PORT}/internal/process`;

  axios.post(safeUrl, { timestamp, nonce, data: req.body })
    .then(response => {
      res.json({ status: 'ok', remoteResponse: response.data });
    })
    .catch(err => {
      console.error('Outbound call failed', err);
      res.status(502).send('Upstream error');
    });
});

app.listen(3000, () => console.log('Server running on port 3000'));

In this pattern, the HMAC covers a canonical representation that includes a fixed method, path, timestamp, and nonce. The outbound call uses a hard‑coded, server‑defined host and port, avoiding any client‑supplied hostname. middleBrick’s checks will validate that the authentication scheme is consistent and that no unchecked redirects or SSRF paths exist, supporting compliance mappings to OWASP API Top 10 and related frameworks.

For automated enforcement in development pipelines, use the CLI to scan early and often: middlebrick scan <url>. Teams on the Pro plan can enable continuous monitoring and CI/CD integration so that changes which weaken binding between HMAC scope and network destination cause builds to fail before deployment.

Frequently Asked Questions

Can an attacker exploit a dangling DNS issue even if the HMAC signature validates successfully?
Yes. If the application uses the client‑supplied hostname for outbound requests after a successful HMAC verification, DNS poisoning or dangling references can redirect traffic to an unintended host. The signature does not protect this confusion because it was computed over the original, attacker‑controlled hostname rather than the final resolved destination.
What is the best practice for binding HMAC signatures to network endpoints in Express?
Include a canonical, server‑defined hostname and port in the signed payload, and avoid using user‑controlled hostnames for outbound calls. Resolve and pin destinations at configuration time, and enforce strict allowlists so that DNS changes cannot redirect requests without detection.