Nosql Injection in Express with Hmac Signatures
Nosql Injection in Express with Hmac Signatures — how this specific combination creates or exposes the vulnerability
NoSQL injection in Express applications that rely on Hmac signatures occurs when user-controlled data used to build database queries is not properly validated or sanitized, while the Hmac-based integrity check is limited to verifying a token or payload structure. Consider an endpoint that accepts a JSON payload and an X-API-Signature header. If the server verifies the Hmac but then directly uses fields from the body (e.g., an identifier or filter key) to construct a NoSQL query, an attacker can supply malicious input that alters query behavior even though the signature is valid. The signature may confirm integrity and authenticity of the data in transit, but it does not sanitize or constrain how the application interprets specific fields for database operations.
For example, an Express route that verifies an Hmac signature and then passes user input directly into a MongoDB query can be abused if the input contains operators such as $gt, $ne, $in, or $where. A benign-looking signature over {"userId": "123", "filter": {"role": {"$ne": ""}}} does not protect the server from unauthorized data access if the application uses the filter object as-is to build a find(query) call. The Hmac check passes, yet the NoSQL injection grants access to other users’ records. This pattern is common in admin or multi-tenant endpoints where identifiers are validated via signature, but parameter values are not constrained.
Another scenario involves query parameters merged with request body data to form a NoSQL query. If the Hmac signature covers only selected headers or a subset of fields, an attacker can inject through unchecked parameters such as sorting or pagination fields (e.g., {"sort": {"$where": "return true"}}). Because the signature mechanism does not inherently enforce schema constraints or whitelist field-level operators, the server may execute unintended commands. This is especially risky when endpoints combine user input with internal logic to build $or, $and, or aggregation pipelines, where injection can bypass intended filters or escalate access.
Sensitive data exposure and authentication bypass are common impacts. Successful NoSQL injection may allow enumeration of usernames via timing differences or error messages, extraction of authentication tokens stored in documents, or elevation to admin privileges if role checks are manipulated. Because Hmac signatures protect integrity but not semantics of the data, developers must treat all user-influenced input as untrusted, regardless of signature presence. The combination of Express routes, Hmac-based client-server authentication, and dynamic NoSQL queries creates an attack surface where trust boundaries are misunderstood, leading to exploitable injection paths.
Hmac Signatures-Specific Remediation in Express — concrete code fixes
Remediation focuses on strict input validation, schema enforcement, and safe query building rather than relying on Hmac signatures alone to ensure safe data handling. Hmac should be used for authenticity and integrity of the payload, but the server must still validate structure, types, and allowed values before using data in a NoSQL query. Below is a secure Express pattern that combines Hmac verification with parameterized query construction and schema checks.
const crypto = require('crypto');
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.json());
const SHARED_SECRET = process.env.HMAC_SECRET;
function verifySignature(req, res, next) {
const signature = req.headers['x-api-signature'];
if (!signature) {
return res.status(401).json({ error: 'Missing signature' });
}
const hmac = crypto.createHmac('sha256', SHARED_SECRET);
hmac.update(JSON.stringify(req.body));
const expected = 'sha256=' + hmac.digest('hex');
if (!crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))) {
return res.status(401).json({ error: 'Invalid signature' });
}
next();
}
// Example schema whitelist for a query filter
const allowedFilterFields = new Set(['userId', 'status', 'tags']);
const allowedOperators = new Set(['$eq', '$in', '$lt', '$lte', '$gt', '$gte']);
function sanitizeFilter(filter) {
if (!filter || typeof filter !== 'object' || Array.isArray(filter)) {
throw new Error('Invalid filter');
}
const cleaned = {};
for (const key of Object.keys(filter)) {
if (!allowedFilterFields.has(key)) {
throw new Error('Disallowed filter field: ' + key);
}
const value = filter[key];
if (typeof value === 'object' && !Array.isArray(value)) {
const nested = {};
for (const op of Object.keys(value)) {
if (!allowedOperators.has(op)) {
throw new Error('Disallowed operator: ' + op);
}
nested[op] = value[op];
}
cleaned[key] = nested;
} else {
cleaned[key] = value;
}
}
return cleaned;
}
app.post('/data', verifySignature, (req, res) => {
try {
const filter = sanitizeFilter(req.body.filter);
// Use a driver method that does not concatenate strings, e.g., parameterized find
// db.collection('items').find(filter).toArray(...)
res.json({ filter });
} catch (err) {
return res.status(400).json({ error: err.message });
}
});
The example demonstrates Hmac verification using crypto.timingSafeEqual to prevent timing attacks, followed by a schema-aware sanitizer that whitelists fields and operators. This ensures that even if the Hmac signature validates the payload, only safe, expected query structures reach the database driver. For pagination and sorting, apply similar strict checks on field names and direction values, avoiding direct use of raw user objects in $orderby or $sort stages.
Additionally, prefer using database driver APIs that accept structured queries without string interpolation, and avoid dynamic construction of queries via eval or concatenation of user input into aggregation pipelines. Logging rejected injection attempts can aid detection without exposing details to the client. Remember that Hmac signatures are an authentication aid; they do not replace input validation, least-privilege access controls, or secure query patterns.