Sql Injection in Feathersjs with Hmac Signatures
Sql Injection in Feathersjs with Hmac Signatures — how this specific combination creates or exposes the vulnerability
FeathersJS is a popular Node.js framework for building REST and real-time APIs. When HMAC signatures are used for request authentication or integrity verification, developers may assume the signed parameters are safe from tampering. However, if a FeathersJS service endpoint builds SQL queries by directly concatenating user-controlled input—even when that input is covered by an HMAC signature—an SQL Injection vulnerability can exist.
The specific combination creates risk when the HMAC is computed over a subset of request data (such as an API key or timestamp) but the developer trusts other parameters that are included in the signed payload. For example, an endpoint might sign the identifier of a resource (e.g., userId) to prevent tampering, yet still interpolate that identifier directly into a SQL string. Because the identifier is signed, the developer may believe it cannot be altered, but the root issue is not the signature; it is the use of string concatenation or non-parameterized queries with data originating from the request.
Consider a route where an HMAC signature is validated to ensure the request has not been modified. If the handler then uses the signed userId in a raw query like SELECT * FROM users WHERE id = ${userId}, the application remains vulnerable. An attacker who can influence the SQL path through other means (such as secondary parameters that are not signed or are used in different query contexts) or who exploits a logic flaw to cause the signed value to be reused in a dynamic query can trigger SQL Injection. In a black-box scan, middleBrick tests such scenarios by checking whether authenticated-like inputs (e.g., those protected by HMAC) are reflected in SQL execution paths and whether untrusted data can modify query structure.
Additionally, if HMAC verification is performed inside a hook that runs before the service method, and that hook modifies request parameters based on the signature without strict validation, untrusted data may be introduced indirectly into SQL-building code. This often occurs when deserialized payload fields are merged into query conditions without type checks or sanitization. The SQL Injection risk is not caused by the HMAC scheme itself, but by the failure to treat request-derived data as untrusted even when it is covered by a signature.
Real-world attack patterns include classic techniques like ' OR 1=1 -- injected into string fields that are concatenated into queries, or numeric fields being supplied with non-numeric input to break query logic. In the context of FeathersJS with HMAC signatures, middleBrick’s checks for Input Validation and BOLA/IDOR help surface cases where endpoints trust signed parameters but still build queries unsafely, leading to findings mapped to OWASP API Top 10 A03:2023 Injection.
Hmac Signatures-Specific Remediation in Feathersjs — concrete code fixes
Remediation focuses on ensuring that all data used to construct SQL statements is handled safely, regardless of whether it is covered by an HMAC. Do not rely on signatures to prevent injection; instead, use parameterized queries or an ORM that enforces separation of code and data. In FeathersJS, this typically involves using Knex or a similar query builder with bound parameters, and validating and sanitizing all inputs within hooks.
Example: Unsafe usage with HMAC
The following example demonstrates an unsafe pattern where an HMAC-signed userId is used to build a raw SQL string. Even though the userId is signed, the query is constructed via string interpolation, which remains dangerous.
// Unsafe: string interpolation with a signed parameter
app.service('users').hooks({
before: {
async get(context) {
const { id, signature } = context.params.query;
if (!verifyHmac(id, signature)) {
throw new Error('Invalid signature');
}
// Dangerous: using id directly in raw SQL
const result = await context.app.get('knex').raw(`SELECT * FROM users WHERE id = ${id}`);
context.result = result.rows;
return context;
}
}
});
Example: Safe remediation using parameterized queries
Use Knex’s parameterized query methods so that user input is never interpreted as SQL code. The HMAC can still be used for integrity, but SQL safety is enforced by the query builder.
// Safe: parameterized query with Knex
app.service('users').hooks({
before: {
async get(context) {
const { id, signature } = context.params.query;
if (!verifyHmac(id, signature)) {
throw new Error('Invalid signature');
}
// Safe: using Knex with bound parameters
const result = await context.app.get('knex')('users').where('id', id);
context.result = result;
return context;
}
}
});
Example: Validating and casting input
Even with parameterized queries, validate and cast input to the expected type. This prevents type confusion and ensures that numeric IDs are not accidentally treated as strings in complex queries.
// Safe with validation and casting
function verifyHmac(data, signature) {
// stub: implement your HMAC verification logic
return true;
}
app.service('users').hooks({
before: {
async get(context) {
const { id, signature } = context.params.query;
if (!verifyHmac(id, signature)) {
throw new Error('Invalid signature');
}
const numericId = Number(id);
if (Number.isNaN(numericId)) {
throw new Error('Invalid user ID');
}
const result = await context.app.get('knex')('users').where('id', numericId);
context.result = result;
return context;
}
}
});
Additional recommendations
- Use FeathersJS hooks to centralize input validation and query building, reducing the chance of mixing trusted and untrusted data in SQL construction.
- If you must construct dynamic SQL, employ strict allowlists for table and column names, and never interpolate them from request data.
- Combine HMAC integrity checks with parameterized queries to achieve both request integrity and SQL safety.
These changes ensure that even if an HMAC-signed parameter is involved, SQL execution remains resilient against injection. middleBrick’s checks for BFLA/Privilege Escalation and Property Authorization can help verify that signed parameters are not misused in privilege-sensitive queries.
Related CWEs: inputValidation
| CWE ID | Name | Severity |
|---|---|---|
| CWE-20 | Improper Input Validation | HIGH |
| CWE-22 | Path Traversal | HIGH |
| CWE-74 | Injection | CRITICAL |
| CWE-77 | Command Injection | CRITICAL |
| CWE-78 | OS Command Injection | CRITICAL |
| CWE-79 | Cross-site Scripting (XSS) | HIGH |
| CWE-89 | SQL Injection | CRITICAL |
| CWE-90 | LDAP Injection | HIGH |
| CWE-91 | XML Injection | HIGH |
| CWE-94 | Code Injection | CRITICAL |