This Vulnerability Explain entry covers NoSQL Injection. As apps moved to databases like MongoDB, the classic SQL injection problem took a new shape. The syntax differs, but the root cause is the same – untrusted input changing the meaning of a query. Let’s look at how it works and how to prevent it.
What is NoSQL Injection?
NoSQL Injection is the manipulation of queries sent to a NoSQL database by injecting input that the database or driver interprets as query operators or code rather than as a plain value.
Many NoSQL databases accept query objects. If an app builds a login query from JSON like {username, password} and passes user input straight in, an attacker can send an operator such as {“$ne”: null} for the password, which means “not equal to null” and matches any record, bypassing authentication.
How does NoSQL Injection work?
NoSQL injection usually takes one of these forms:
- Input Reaches the Query
- User input is placed directly into a query object or string.
- Operator Injection
- The attacker supplies query operators like $ne, $gt, $regex, or $where instead of a plain value.
- Logic Is Altered
- The injected operators change the query’s meaning, for example matching all records or always evaluating true.
- JavaScript Evaluation
- Some engines evaluate JavaScript (for example $where), allowing more powerful injection.
- Impact
- Outcomes include authentication bypass, data exfiltration, and in some cases denial of service or code execution.
NoSQL injection proves that abandoning SQL does not abandon injection. Any time input can become part of the query structure, the logic can be hijacked.

Tools and Techniques for NoSQL Injection Testing
Testing focuses on operator injection and, where relevant, server-side JavaScript.
Manual Testing Methodologies
- Operator Injection – Replace string values with objects like {“$ne”: null} or {“$gt”: “”} in JSON bodies and parameters.
- Authentication Bypass Probes – Target login endpoints with operator payloads in username and password fields.
- Regex and Where Testing – Try $regex for blind extraction and $where for JavaScript evaluation where supported.
- Parameter Pollution – Test how the framework parses arrays and objects from query strings (for example user[$ne]=null).
Automated Scanning Tools
- NoSQLMap – Automates detection and exploitation of NoSQL injection.
- nosqli – A focused NoSQL injection scanner.
- Burp Suite Scanner – Detects injection issues including NoSQL patterns.
- Nuclei – Community templates for common NoSQL injection cases.
NoSQL Injection Protection Mechanisms
Best Practices for Secure Coding
- Validate and Cast Input Types
- Description: Enforce that values are the expected primitive type, not objects.
- Benefits: Stops operator injection at the door.
- Implementation Tip: Reject request fields that arrive as objects or arrays where a string is expected.
- Use Safe Query Builders
- Description: Use driver APIs and ODMs that separate data from query structure.
- Benefits: Input is treated strictly as values.
- Implementation Tip: Avoid passing raw request bodies directly into query filters.
- Disable Server-Side JavaScript
- Description: Turn off features like $where and mapReduce JavaScript where not needed.
- Benefits: Removes the most dangerous evaluation paths.
- Implementation Tip: Set the engine to disable JavaScript execution.
Best Practices for Organizations
- Schema Validation
- Enforce database-level schema validation.
- Validate request bodies against a strict schema before querying.
- Least Privilege
- Use database accounts with minimal rights.
- Separate read and write credentials.
- Testing
- Add NoSQL injection tests to CI.
- Pentest authentication and search endpoints specifically.
Top NoSQL Injection payloads used by Security Researchers
As a security researcher, knowing the most common payloads helps you detect and prevent these attacks. Use this knowledge ethically and only on systems you are authorized to test. Some sample payloads are shown below.
// Authentication bypass via operator injection (JSON body)
{ "username": "admin", "password": { "$ne": null } }// Match-all using comparison operators
{ "username": { "$gt": "" }, "password": { "$gt": "" } }// Query-string operator injection
username[$ne]=null&password[$ne]=null// JavaScript evaluation via $where (if enabled)
{ "$where": "this.password.length > 0" }Real-World Example: Login Bypass with $ne
A Node.js app authenticated users by passing the JSON request body straight into a MongoDB findOne filter: { username, password }.
A tester sent { “username”: “admin”, “password”: { “$ne”: null } }. Because $ne null matches any non-null password, the query returned the admin record and logged the tester in without knowing the password.
The fix validated that username and password were strings and rejected object values. NoSQL injection shows that the database technology changes, but never trusting input to shape a query is timeless.
Vulnerable and secure code of NoSQL Injection
The following example shows the contrast between vulnerable and secure code for NoSQL Injection. It helps you see how the flaw creeps into real code and the changes that shut it down.
🥺 Vulnerable Code:
// Vulnerable: request body passed straight into the query
app.post("/login", async (req, res) => {
const { username, password } = req.body;
// password can arrive as { "$ne": null } and match any record
const user = await db.collection("users").findOne({ username, password });
if (user) return res.send("Logged in");
res.status(401).send("Invalid");
});- The body is used directly, so an attacker can inject MongoDB operators.
- A payload like {“$ne”: null} bypasses the password check entirely.
😎 Secure Code:
// Secure: enforce string types before querying
app.post("/login", async (req, res) => {
const { username, password } = req.body;
if (typeof username !== "string" || typeof password !== "string") {
return res.status(400).send("Invalid input");
}
const user = await db.collection("users").findOne({ username });
if (user && await bcrypt.compare(password, user.passwordHash)) {
return res.send("Logged in");
}
res.status(401).send("Invalid");
});- Type checks reject object payloads, so operator injection is impossible.
- Passwords are verified against a hash, not matched directly in the query.
Conclusion
NoSQL injection is proof that injection is a design problem, not a SQL problem. Validate and cast input to its expected primitive type, use query builders that keep data separate from structure, disable server-side JavaScript you do not need, and apply schema validation. Treat every request field as untrusted data, and the database – SQL or not – stays in your control.