← CodeClarityLab Home
Browse by Category
+ added · updated 7d
← Back to glossary

NoSQL Injection

security CWE-943 OWASP A3:2021 CVSS 8.8 PHP 5.4+ Intermediate

Also Known As

NoSQL injection MongoDB injection document store injection operator injection $where injection

TL;DR

Attacker-controlled input embedded into NoSQL queries (MongoDB, Redis, Couchbase) that subverts query intent — bypassing auth, exfiltrating data, or executing server-side code.

Explanation

NoSQL injection is the document-store equivalent of SQL injection, but with attack vectors specific to each engine. In MongoDB, the most common patterns are: operator injection where attacker input becomes a query operator object (e.g. submitting `{"$ne": null}` as a password to bypass a `find({user, password})` query); JavaScript injection via the `$where` operator or `mapReduce`, which executes attacker-controlled JS server-side; and array/object payload injection in fields the application expects to be strings. Redis vulnerabilities cluster around `EVAL`, `SCRIPT LOAD`, and command injection through unvalidated arguments to Lua scripts. Couchbase and other engines have N1QL injection that closely mirrors SQL injection. The unifying defence is the same as SQL: never concatenate untrusted input into queries; use parameterised query builders, type-cast inputs to expected scalar types before query construction, and validate that JSON inputs match a strict schema. PHP's MongoDB driver (`mongodb/mongodb`) accepts BSON arrays — type-casting `$_POST` values to strings before passing them to a query is a critical defensive step.

How It's Exploited

Login bypass: POST `username=admin&password[$ne]=x` — MongoDB matches any password where the field is not equal to 'x', returning the admin record. Data exfiltration: `username[$regex]=^a` — enumerate accounts character-by-character. RCE on `$where`: `username=admin'; sleep(5000); var x='` — server-side JS execution.

Watch Out

json_decode($input, true) returns associative arrays — passing the result into a query is the exact same vulnerability as passing $_POST directly. Type-cast and validate every field individually.

Common Misconception

NoSQL databases are immune to injection because they don't use SQL. They are not — they accept structured query objects, and any pathway that lets an attacker control the structure of those objects (not just the values) is an injection vector. Operator injection with `$ne`, `$gt`, or `$where` can bypass authentication or extract data without ever touching SQL syntax.

Why It Matters

PHP applications that pass `$_POST` values directly into MongoDB queries are routinely exploitable via JSON-encoded operator payloads. Authentication bypass is trivial — login forms that compare `find(['user' => $u, 'pass' => $p])` accept `pass[$ne]=` as a query-string payload that matches any password. Stored data exfiltration follows from there.

Common Mistakes

  • Passing `$_POST` arrays straight into MongoDB queries — PHP arrays serialize to BSON objects, turning user input into operator structure.
  • Using `$where` with concatenated user input — equivalent to executing attacker-controlled JavaScript server-side.
  • Assuming JSON parsing sanitises input — `json_decode` happily produces nested arrays that become query operators.
  • Treating Redis as injection-free — `EVAL` with concatenated arguments, or commands constructed from user input, are RCE-class vulnerabilities.
  • Filtering only string-keys without filtering values — operator injection happens through values that contain keys starting with `$`.

Avoid When

  • Code uses a typed query-builder with parameterised values and no raw arrays — validate that's actually the case before assuming safety.

When To Use

  • Reviewing any PHP code that builds MongoDB or Redis queries from request input.
  • Auditing authentication, search, and update endpoints in document-store applications.
  • Setting up CI rules to catch direct $_POST/$_GET use in query construction.

Code Examples

💡 Note
Casting to (string) is the minimal fix; production code should also validate input shape and use $eq explicitly when comparing user input to fields, never letting raw associative arrays reach the query.
✗ Vulnerable
// ❌ MongoDB query built from raw $_POST — accepts operator injection
$user = $collection->findOne([
    'username' => $_POST['username'],
    'password' => $_POST['password']
]);
// Attacker submits password[$ne]=x — matches any non-'x' password.
// Authentication bypass is one form post away.
✓ Fixed
// ✅ Cast to scalar string and validate — operator structure cannot survive
$username = (string) ($_POST['username'] ?? '');
$password = (string) ($_POST['password'] ?? '');

if ($username === '' || $password === '' || strlen($password) > 1024) {
    throw new InvalidArgumentException('Invalid credentials format');
}

$user = $collection->findOne([
    'username' => $username,
    'password' => password_verify_lookup($password)
]);

// For arbitrary user input that must be JSON, validate against a schema
// (e.g. opis/json-schema) before passing fields to the query builder.

Added 28 Apr 2026
Views 10
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings W 0 pings T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 0 pings S 0 pings M 4 pings T 0 pings W 0 pings T 0 pings F 1 ping S 1 ping S 0 pings M 0 pings T 0 pings W 0 pings T
No pings yet today
No pings yesterday
ChatGPT 2 Google 2 Perplexity 2
crawler 4 crawler_json 2
DEV INTEL Tools & Severity
🟠 High ⚙ Fix effort: Low
⚡ Quick Fix
Type-cast every user-supplied value to its expected scalar type (string, int) before placing it in a query array. Reject inputs whose JSON-decoded form contains keys starting with `$`.
📦 Applies To
PHP 5.4+ web cli queue-worker
🔗 Prerequisites
🔍 Detection Hints
MongoDB collection methods (findOne, find, updateOne) called with $_POST, $_GET, or json_decode result without type-casting
Auto-detectable: ✓ Yes semgrep psalm
⚠ Related Problems
🤖 AI Agent
Confidence: High False Positives: Low ✗ Manual fix Fix: Low Context: Function Tests: Update
CWE-943 CWE-89

✓ schema.org compliant