MongoDB injection
Description
MongoDB injection is a security vulnerability that occurs when user-supplied input is incorporated into MongoDB queries without proper validation or sanitization. Similar to SQL injection, attackers can manipulate query logic by injecting malicious operators or JavaScript code. This vulnerability commonly arises in two forms: Operation Injection, where attackers insert MongoDB operators (such as $ne, $gt, or $where) through associative arrays in request parameters, and Script Injection, where malicious JavaScript code is executed within MongoDB's server-side JavaScript context. Applications that directly pass user input from GET/POST parameters into database queries are particularly vulnerable.
Remediation
Implement the following security measures to prevent MongoDB injection attacks:
1. Input Validation and Type Casting:
Always validate and cast user input to the expected data type before using it in queries. Ensure that parameters intended to be strings are explicitly converted:
// PHP Example - Cast input to string $username = (string)$_POST['username']; $collection->findOne(['username' => $username]);
2. Use Parameterized Queries:
Avoid string concatenation or interpolation when building queries. Use the native query structure provided by your MongoDB driver:
// Node.js Example - Proper parameterization
const query = { username: req.body.username };
db.collection('users').findOne(query);
3. Sanitize Associative Arrays:
Reject or sanitize input that contains MongoDB operators (keys starting with $). Implement whitelist validation for expected input formats:
// PHP Example - Reject operator injection
function sanitizeInput($input) {
if (is_array($input)) {
foreach ($input as $key => $value) {
if (strpos($key, '$') === 0) {
throw new Exception('Invalid input detected');
}
}
}
return $input;
}
4. Avoid Server-Side JavaScript:
Minimize or eliminate use of $where, MapReduce, and other JavaScript execution features. If necessary, use the scope parameter to pass variables rather than string interpolation:
// Unsafe - JavaScript interpolation
db.collection.find({ $where: "this.username == '" + userInput + "'" });
// Safe - Using scope parameter
db.collection.find({
$where: function() { return this.username == username; },
scope: { username: userInput }
});
5. Implement Least Privilege:
Configure database user permissions to restrict access to only necessary operations and collections, limiting the potential damage from successful injection attacks.