Nosql Injection in Express
How Nosql Injection Manifests in Express
Nosql Injection in Express applications typically occurs when user-supplied data flows directly into MongoDB queries without proper sanitization. Express's middleware architecture makes it particularly vulnerable to this attack vector because request parameters, query strings, and body data are automatically parsed and made available to route handlers.
The most common attack pattern involves manipulating query parameters to alter the structure of MongoDB operations. For example, an Express route handling a product search might look like:
app.get('/api/products', (req, res) => {
const { category, price } = req.query;
const query = {
category,
price: { $lt: price }
};
Product.find(query).then(products => res.json(products));
});An attacker can exploit this by sending a request like /api/products?category=electronics&price[$ne]=0. This modifies the query to return all products where price is not equal to zero, effectively bypassing any price filtering logic.
Another common vulnerability appears in Express routes that use req.body for MongoDB operations. Consider an update endpoint:
app.put('/api/users/:id', (req, res) => {
const updates = req.body;
User.findByIdAndUpdate(req.params.id, updates, { new: true })
.then(user => res.json(user));
});An attacker can send a JSON payload like { "$set": { "admin": true }, "$where": "sleep(1000) && 1" } to escalate privileges and execute arbitrary JavaScript in the MongoDB query engine.
Express's body parsing middleware (express.json()) doesn't validate the structure of incoming data, making it easy for attackers to craft malicious payloads. The framework's permissive nature means that any route handling user input for database operations is a potential injection point.
Express-Specific Detection
Detecting NoSQL injection in Express applications requires both static analysis and runtime scanning. middleBrick's API security scanner is specifically designed to identify these vulnerabilities by testing the unauthenticated attack surface of your Express endpoints.
When middleBrick scans an Express API, it automatically tests for NoSQL injection by sending specially crafted payloads to all endpoints. For example, it will test parameters like:
{
"$ne": null,
"$gt": -1,
"$where": "this.password.length > 0"
}The scanner evaluates how your Express application handles these payloads and checks if they alter query behavior or expose sensitive data. middleBrick's 12 security checks include specific tests for NoSQL injection patterns, examining both query parameters and request bodies.
For Express applications, middleBrick also analyzes the OpenAPI/Swagger specification if provided, mapping endpoint definitions to runtime findings. This helps identify endpoints that accept complex objects or arrays, which are common injection vectors in NoSQL databases.
Manual detection in Express involves reviewing route handlers that interact with MongoDB. Look for patterns where:
- User input is directly assigned to query objects
- Request parameters are used without validation
- Body data is passed directly to database operations
- Dynamic field names are constructed from user input
middleBrick's dashboard provides a security score (A–F) and highlights specific findings with severity levels, making it easy to prioritize remediation efforts across your Express application.
Express-Specific Remediation
Remediating NoSQL injection in Express applications requires a combination of input validation, query sanitization, and secure coding practices. The most effective approach is to use MongoDB's built-in validation features along with Express middleware for input sanitization.
First, implement strict input validation using a schema validation library like Joi or Yup:
const Joi = require('joi');
const productSchema = Joi.object({
category: Joi.string().valid('electronics', 'books', 'clothing').required(),
price: Joi.number().min(0).max(10000).required()
});
app.get('/api/products', (req, res) => {
const { error, value } = productSchema.validate(req.query);
if (error) {
return res.status(400).json({ error: 'Invalid input' });
}
const query = {
category: value.category,
price: { $lt: value.price }
};
Product.find(query).then(products => res.json(products));
});For routes that update documents, use a whitelist approach to prevent injection:
app.put('/api/users/:id', (req, res) => {
const allowedUpdates = ['name', 'email', 'password'];
const updates = Object.keys(req.body).filter(key => allowedUpdates.includes(key));
if (updates.length === 0) {
return res.status(400).json({ error: 'No valid fields provided' });
}
User.findByIdAndUpdate(req.params.id, { $set: req.body }, { new: true })
.then(user => res.json(user));
});Express middleware can centralize input sanitization:
const sanitizeInput = (req, res, next) => {
const sanitize = (obj) => {
if (Array.isArray(obj)) {
return obj.map(sanitize);
} else if (typeof obj === 'object' && obj !== null) {
const sanitized = {};
for (const [key, value] of Object.entries(obj)) {
if (key.startsWith('$')) {
throw new Error('Invalid field name');
}
sanitized[key] = sanitize(value);
}
return sanitized;
}
return obj;
};
try {
req.body = sanitize(req.body);
req.query = sanitize(req.query);
next();
} catch (error) {
res.status(400).json({ error: 'Invalid input' });
}
};
app.use(express.json());
app.use(sanitizeInput);For production Express applications, integrate middleBrick's CLI into your development workflow to continuously scan for NoSQL injection vulnerabilities:
npm install -g middlebrick
middlebrick scan https://api.yourapp.comThe Pro plan includes continuous monitoring, automatically scanning your Express APIs on a configurable schedule and alerting you to new vulnerabilities as they emerge.