Beast Attack in Feathersjs with Hmac Signatures
Beast Attack in Feathersjs with Hmac Signatures — how this specific combination creates or exposes the vulnerability
A Beast Attack (BOLA/IDOR) in a Feathersjs service that uses Hmac Signatures can occur when signature verification is applied inconsistently across endpoints or when the signature does not bind to the resource owner or record identifier. Feathersjs is a flexible framework; without strict per-request validation, an attacker who can influence the identifier used in the signature (e.g., by manipulating a query or parameter) may be able to reuse a captured signature for a different resource or escalate behavior.
Hmac Signatures are typically computed over a combination of method, path, timestamp, nonce, and a payload or selected fields. If the signature is computed over a resource ID supplied by the client and the server does not re-associate that ID with the authenticated principal, an attacker can substitute another ID and replay the signed request. This maps to OWASP API Top 10:2023 Broken Object Level Authorization (BOLA)/Insecure Direct Object Reference (IDOR). For example, an endpoint like /messages/{id} signed by the client could allow an attacker to iterate IDs if the server does not confirm that the signed ID belongs to the caller.
In Feathersjs, a typical vulnerable pattern is to sign the entire request including an id query parameter and then process the request without verifying that the id aligns with the user’s permissions. The signature may validate integrity and timestamp, but it does not inherently enforce ownership. Additionally, if different endpoints share the same key material and signature scheme but apply different canonicalization rules, an attacker might leverage inconsistencies (e.g., one endpoint includes a trailing slash while another does not) to generate valid signatures for unauthorized resources.
The risk is compounded when replay protections like nonce and timestamp windows are not enforced uniformly. An intercepted signed request could be replayed within the validity window to perform unauthorized actions on a different resource (the "beast"), especially when rate limiting or audit logging is absent or misconfigured. This is a runtime behavior issue: the API remains unauthenticated from the scanner’s perspective, and middleBrick can detect whether signature validation is applied consistently across the unauthenticated attack surface.
To detect such issues, middleBrick runs parallel security checks including BOLA/IDOR and Property Authorization, and it cross-references OpenAPI/Swagger specs (with full $ref resolution) against runtime findings. This helps identify mismatches between documented authentication expectations and actual endpoint behavior when Hmac Signatures are used.
Hmac Signatures-Specific Remediation in Feathersjs — concrete code fixes
Remediation focuses on ensuring that the Hmac signature binds the request to the authenticated principal and the exact resource, and that verification is applied consistently across all Feathersjs services.
- Include the user identifier in the signature scope: When computing the Hmac, incorporate a stable user ID (e.g., from an authentication strategy) so that signatures cannot be reused across users.
- Validate resource ownership after signature verification: After verifying the Hmac, re-check that the resource ID in the request belongs to the authenticated principal before proceeding.
- Use a strict canonicalization policy: Ensure consistent ordering, encoding, and inclusion/exclusion of fields (such as omitting empty values) across all services.
- Enforce nonce/timestamp validation server-side: Maintain a server-side cache or short-term store to reject replays within the validity window.
- Apply signature verification middleware uniformly: Do not skip verification for "internal" or documentation endpoints.
Example: A secure Feathersjs service using an Hmac signature scheme with a user-specific key and resource binding:
const crypto = require('crypto');
function verifyHmac(req) {
const { method, url, timestamp, nonce, id, body } = req.headers;
const providedSignature = req.headers['x-signature'];
const user = req.user; // authenticated principal from feathers-authentication
if (!user || !user.id) {
throw new Error('Unauthorized');
}
const key = user.hmacKey; // stored per-user secret or derived securely
const payload = JSON.stringify(body || {});
const data = `${method}|${url}|${timestamp}|${nonce}|${id}|${payload}`;
const expected = crypto.createHmac('sha256', key).update(data).digest('hex');
const tolerance = 30; // seconds
if (Math.abs(Date.now() / 1000 - parseInt(timestamp, 10)) > tolerance) {
throw new Error('Request expired');
}
if (!crypto.timingSafeEqual(Buffer.from(providedSignature, 'hex'), Buffer.from(expected, 'hex'))) {
throw new Error('Invalid signature');
}
// Ensure the requested id matches the user's ownership
if (id && user.id !== id) {
throw new Error('Forbidden: resource mismatch');
}
return true;
}
// Feathersjs service hook
const { authenticate } = require('@feathersjs/authentication').hooks;
module.exports = {
before: {
all: [authenticate('jwt')], // or your auth strategy
find: [verifyHmac],
get: [verifyHmac],
create: [verifyHmac],
update: [verifyHmac],
patch: [verifyHmac],
remove: [verifyHmac]
],
after: {
all: [],
find: [],
get: [],
create: [],
update: [],
patch: [],
remove: []
},
error: {}
};
In the above, the signature scope includes method, URL, timestamp, nonce, resource id, and the request body, and ownership is explicitly verified after signature validation. This prevents signature reuse across users or resources. The same verification hook is applied across all HTTP methods to avoid inconsistent coverage.
middleBrick can validate that such hooks exist and that the signature scope does not leak sensitive data or accept ambiguous inputs. Its LLM/AI Security checks can also ensure that prompt injection or data exfiltration probes do not exploit inconsistent authentication in AI-assisted API workflows.