Header Injection in Mongodb
How Header Injection Manifests in Mongodb
Header injection vulnerabilities in Mongodb applications occur when user-controlled HTTP headers are incorporated into database queries without proper validation or sanitization. Unlike SQL injection where malicious input is injected into SQL statements, header injection in Mongodb targets the NoSQL query construction process.
The most common manifestation involves HTTP headers being used to construct dynamic query parameters. Consider a REST API endpoint that accepts a user ID from a custom header:
const express = require('express');
const app = express();
app.get('/api/profile', (req, res) => {
const userId = req.headers['x-user-id'];
const user = db.collection('users').findOne({ _id: userId });
res.json(user);
});An attacker can exploit this by sending a malicious X-User-Id header value that manipulates the query structure. Mongodb's query language accepts operators like $ne, $gt, $regex, and $where that can be used to bypass authentication or access unauthorized data.
Another attack vector involves using headers to construct aggregation pipelines. If an API endpoint accepts header values to build pipeline stages:
app.get('/api/reports', (req, res) => {
const pipeline = [
{ $match: { status: req.headers['x-status'] } },
{ $group: { _id: '$department', total: { $sum: '$amount' } } }
];
db.collection('transactions').aggregate(pipeline).toArray();
});An attacker could inject pipeline operators through the X-Status header, potentially accessing all documents regardless of status or manipulating the aggregation logic.
Header injection also manifests in Mongodb through improper handling of projection fields. When API endpoints use headers to determine which fields to return:
app.get('/api/user/:id', (req, res) => {
const projection = { [req.headers['x-fields']]: 1 };
db.collection('users').findOne({ _id: req.params.id }, { projection });
});An attacker could use field name injection to access sensitive fields or manipulate the projection structure to bypass authorization checks.
Mongodb-Specific Detection
Detecting header injection in Mongodb applications requires understanding both the HTTP layer and the NoSQL query structure. MiddleBrick's black-box scanning approach identifies these vulnerabilities by systematically testing API endpoints with malicious header values.
The scanner tests for common Mongodb injection patterns including operator injection, where it attempts to inject operators like $ne: null, $gt: 0, and $exists: true through various HTTP headers. It also tests for aggregation pipeline injection by attempting to inject pipeline operators like $project, $match, and $group.
MiddleBrick's detection engine specifically looks for Mongodb's unique query syntax patterns. For example, it tests whether an endpoint is vulnerable to the following injection attempt:
GET /api/profile HTTP/1.1
Host: example.com
X-User-Id: {"$ne": null}If this returns user data without authentication, the scanner identifies a BOLA (Broken Object Level Authorization) vulnerability specific to Mongodb's query language.
The scanner also tests for projection field injection by attempting to access restricted fields through header manipulation:
GET /api/user/123 HTTP/1.1
Host: example.com
X-Fields: "password"MiddleBrick's Mongodb-specific checks include testing for regex injection patterns that can cause denial of service through expensive pattern matching, and $where clause injection that allows arbitrary JavaScript execution within Mongodb queries.
For applications using Mongodb's aggregation framework, the scanner tests pipeline injection by attempting to append malicious stages to existing pipelines through header values. This includes testing for stage injection that could manipulate query results or access unauthorized data.
MiddleBrick provides detailed findings that map to OWASP API Top 10 categories, specifically identifying BOLA/IDOR vulnerabilities when header injection allows unauthorized data access, and Input Validation failures when user-controlled headers are incorporated into queries without sanitization.
Mongodb-Specific Remediation
Remediating header injection vulnerabilities in Mongodb applications requires a defense-in-depth approach that validates input at multiple layers. The first line of defense is strict input validation and sanitization of all HTTP headers before they're used in database queries.
For user ID parameters that come from headers, implement strict type validation:
const ObjectId = require('mongodb').ObjectId;
function validateUserId(headerValue) {
if (!headerValue || typeof headerValue !== 'string') {
throw new Error('Invalid user ID format');
}
try {
return new ObjectId(headerValue);
} catch (error) {
throw new Error('Invalid ObjectId format');
}
}
app.get('/api/profile', (req, res) => {
const userId = validateUserId(req.headers['x-user-id']);
const user = db.collection('users').findOne({ _id: userId });
res.json(user);
});This approach ensures that only valid Mongodb ObjectIds can be used in queries, preventing operator injection attacks.
For query parameter construction, use explicit field whitelisting instead of dynamic field names:
const VALID_FIELDS = ['name', 'email', 'department'];
function sanitizeProjection(fieldsHeader) {
if (!fieldsHeader || typeof fieldsHeader !== 'string') {
return {};
}
const requestedFields = fieldsHeader.split(',').map(f => f.trim());
const projection = {};
for (const field of requestedFields) {
if (VALID_FIELDS.includes(field)) {
projection[field] = 1;
}
}
return projection;
}
app.get('/api/user/:id', (req, res) => {
const projection = sanitizeProjection(req.headers['x-fields']);
db.collection('users').findOne({ _id: req.params.id }, { projection });
});This prevents field name injection by only allowing predefined fields in the projection.
For aggregation pipeline construction, avoid dynamic pipeline building from user input. Instead, use predefined pipeline stages with parameterized values:
function buildSafePipeline(status, department) {
const stages = [];
if (status) {
stages.push({ $match: { status: { $in: status.split(',') } } });
}
if (department) {
stages.push({ $match: { department: department } });
}
stages.push({
$group: {
_id: '$department',
total: { $sum: '$amount' }
}
});
return stages;
}
app.get('/api/reports', (req, res) => {
const pipeline = buildSafePipeline(
req.query.status,
req.query.department
);
db.collection('transactions').aggregate(pipeline).toArray();
});This approach ensures that only safe, predefined pipeline structures are used, preventing pipeline injection attacks.
Implement comprehensive logging and monitoring to detect suspicious query patterns. Log all queries that include operators or patterns that deviate from normal application behavior, and set up alerts for potential injection attempts.
Consider using Mongodb's built-in query sanitizers or database-level query whitelisting if available in your deployment configuration. These features can help prevent certain types of injection attacks at the database level.