HIGH brute force attackfeathersjshmac signatures

Brute Force Attack in Feathersjs with Hmac Signatures

Brute Force Attack in Feathersjs with Hmac Signatures — how this specific combination creates or exposes the vulnerability

A brute force attack against an API that uses Hmac signatures in Feathersjs can occur when the service authenticates requests with a static or low-entropy secret combined with a predictable or reused nonce/identifier. Feathersjs does not enforce built-in brute force protections for Hmac-authenticated routes by default. If an endpoint accepts Hmac-signed requests without additional safeguards (such as per-request nonces, timestamps, or rate limiting), an attacker can systematically guess valid signatures or replay captured signatures to gain unauthorized access.

Consider a Feathers service where the client computes an Hmac over a combination of timestamp, user identifier, and a shared secret, then sends it in a header (e.g., x-api-hmac). If the server validates the signature but does not ensure freshness (e.g., reject requests with timestamps outside a narrow window) and does not track or reject replayed nonces, the same signed payload can be reused. An attacker who observes a valid signed request can replay it, or perform a brute force attempt against weak shared secrets or predictable inputs. Feathersjs routes that rely only on Hmac for authentication without additional anti-replay or rate limiting expose an attack surface where brute force or replay can lead to unauthorized data access or privilege escalation.

For example, an endpoint like /api/messages that uses Hmac for authentication but lacks per-request nonce validation or rate limiting may allow an attacker to submit thousands of signed requests with slightly altered inputs, testing guessed secrets or replaying intercepted signatures. Because the validation logic may only check cryptographic correctness and not invocation count or timing, brute force attempts can succeed silently. The combination of Feathersjs service hooks that trust Hmac-verified headers and missing runtime protections (e.g., sliding window checks, monotonic counters) turns a cryptographic integrity check into a weak authentication primitive when brute force or replay is feasible.

Hmac Signatures-Specific Remediation in Feathersjs — concrete code fixes

To mitigate brute force and replay risks when using Hmac signatures in Feathersjs, introduce per-request nonces or timestamps with server-side tracking, enforce short validity windows, and apply rate limiting on a per-client basis. Below are concrete code examples that demonstrate a hardened approach.

Example Hmac signature generation (client)

const crypto = require('crypto');

function signRequest({ method, path, timestamp, nonce, body }, sharedSecret) {
  const payload = `${method}:${path}:${timestamp}:${nonce}:${JSON.stringify(body)}`;
  return crypto.createHmac('sha256', sharedSecret).update(payload).digest('hex');
}

const sharedSecret = process.env.SHARED_SECRET;
const timestamp = Date.now();
const nonce = crypto.randomBytes(8).toString('hex');
const signature = signRequest({
  method: 'POST',
  path: '/messages',
  timestamp,
  nonce,
  body: { text: 'hello' }
}, sharedSecret);

// send headers: x-api-timestamp, x-api-nonce, x-api-hmac

Example Hmac signature verification (Feathersjs service hook)

const crypto = require('crypto');

// In-memory store for replay protection (use Redis in production)
const seenNonces = new Set();

function verifyHmac(req) {
  const timestamp = req.headers['x-api-timestamp'];
  const nonce = req.headers['x-api-nonce'];
  const receivedHmac = req.headers['x-api-hmac'];

  if (!timestamp || !nonce || !receivedHmac) {
    throw new Error('Missing authentication headers');
  }

  // Reject stale requests (e.g., 5-minute window)
  const now = Date.now();
  const skew = 300000; // 5 minutes
  if (Math.abs(now - Number(timestamp)) > skew) {
    throw new Error('Request expired');
  }

  // Replay protection
  if (seenNonces.has(nonce)) {
    throw new Error('Replay detected');
  }
  seenNonces.add(nonce);

  // Compute expected Hmac (same logic as client)
  const payload = `${req.method}:${req.path}:${timestamp}:${nonce}:${JSON.stringify(req.body || {})}`;
  const expectedHmac = crypto.createHmac('sha256', process.env.SHARED_SECRET).update(payload).digest('hex');

  if (!crypto.timingSafeEqual(Buffer.from(receivedHmac), Buffer.from(expectedHmac))) {
    throw new Error('Invalid signature');
  }
}

// Register as a before hook
module.exports = function() {
  return async context => {
    verifyHmac(context.params.raw);
    return context;
  };
};

Rate limiting and additional protections

Complement Hmac verification with rate limiting on a per-client basis (e.g., by IP or API key derived from the Hmac). Below is a concise example using an in-memory map; in production, use a distributed store and integrate with Feathers hooks.

const rateLimitWindowMs = 60000; // 1 minute
const maxRequestsPerWindow = 30;
const requestCounts = new Map();

function rateLimit(context) {
  const clientId = context.params.headers['x-api-client'] || context.connection.remoteAddress;
  const now = Date.now();
  const windowStart = now - rateLimitWindowMs;

  if (!requestCounts.has(clientId)) {
    requestCounts.set(clientId, []);
  }
  const timestamps = requestCounts.get(clientId);
  // Purge old entries
  const recent = timestamps.filter(t => t >= windowStart);
  recent.push(now);
  requestCounts.set(clientId, recent);

  if (recent.length > maxRequestsPerWindow) {
    throw new Error('Rate limit exceeded');
  }
  return context;
}

// Chain with Hmac hook
module.exports = function() {
  return async context => {
    verifyHmac(context.params.raw);
    rateLimit(context);
    return context;
  };
};

These measures ensure that Hmac signatures in Feathersjs are bound to fresh, non-replayed requests and that brute force or replay attempts are effectively mitigated. The server-side validation must check timestamp freshness, reject reused nonces, and enforce rate limits to prevent successful brute force attacks.

Frequently Asked Questions

What specific risks does replaying Hmac-signed requests introduce in Feathersjs?
Replayed Hmac-signed requests can bypass authentication if the server does not enforce nonces or timestamps, allowing an attacker to reuse a captured valid signature to access or modify resources.
Why is rate limiting important when using Hmac signatures in Feathersjs?
Rate limiting prevents brute force attempts by limiting the number of requests a client can make in a time window, reducing the risk of successful signature guessing or replay attacks.