> For the complete documentation index, see [llms.txt](https://dev-angelist.gitbook.io/ewptxv3-notes/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://dev-angelist.gitbook.io/ewptxv3-notes/readme/5.5-other-common-web-attacks-1/system-security-1/4.3.5-nosql.md).

# 4.3.5 NoSQL

## NoSQL injection

NoSQL injection is a vulnerability where an attacker is able to interfere with the queries that an application makes to a NoSQL database. NoSQL injection may enable an attacker to:

* Bypass authentication or protection mechanisms.
* Extract or edit data.
* Cause a denial of service.
* Execute code on the server.

NoSQL databases store and retrieve data in a format other than traditional SQL relational tables. They use a wide range of query languages instead of a universal standard like SQL, and have fewer relational constraints.

## MongoDB NoSQL Injection

#### Detecting operator injection in MongoDB <a href="#detecting-operator-injection-in-mongodb" id="detecting-operator-injection-in-mongodb"></a>

Consider a vulnerable application that accepts a username and password in the body of a `POST` request:

`{"username":"wiener","password":"peter"}`

Test each input with a range of operators. For example, to test whether the username input processes the query operator, you could try the following injection:

`{"username":{"$ne":"invalid"},"password":"peter"}`

If the `$ne` operator is applied, this queries all users where the username is not equal to `invalid`.

If both the username and password inputs process the operator, it may be possible to bypass authentication using the following payload:

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

This query returns all login credentials where both the username and password are not equal to `invalid`. As a result, you're logged into the application as the first user in the collection.

To target an account, you can construct a payload that includes a known username, or a username that you've guessed. For example:

`{"username":{"$in":["admin","administrator","superadmin"]},"password":{"$ne":""}}`

### Exploiting syntax injection to extract data <a href="#exploiting-syntax-injection-to-extract-data" id="exploiting-syntax-injection-to-extract-data"></a>

In many NoSQL databases, some query operators or functions can run limited JavaScript code, such as MongoDB's `$where` operator and `mapReduce()` function. This means that, if a vulnerable application uses these operators or functions, the database may evaluate the JavaScript as part of the query. You may therefore be able to use JavaScript functions to extract data from the database.

#### Exfiltrating data in MongoDB <a href="#exfiltrating-data-in-mongodb" id="exfiltrating-data-in-mongodb"></a>

Consider a vulnerable application that allows users to look up other registered usernames and displays their role. This triggers a request to the URL:

`https://insecure-website.com/user/lookup?username=admin`

This results in the following NoSQL query of the `users` collection:

`{"$where":"this.username == 'admin'"}`

As the query uses the `$where` operator, you can attempt to inject JavaScript functions into this query so that it returns sensitive data. For example, you could send the following payload:

`admin' && this.password[0] == 'a' || 'a'=='b`

This returns the first character of the user's password string, enabling you to extract the password character by character.

You could also use the JavaScript `match()` function to extract information. For example, the following payload enables you to identify whether the password contains digits:

`admin' && this.password.match(/\d/) || 'a'=='b`

### Injecting operators in MongoDB <a href="#injecting-operators-in-mongodb" id="injecting-operators-in-mongodb"></a>

Consider a vulnerable application that accepts username and password in the body of a `POST` request:

`{"username":"wiener","password":"peter"}`

To test whether you can inject operators, you could try adding the `$where` operator as an additional parameter, then send one request where the condition evaluates to false, and another that evaluates to true. For example:

`{"username":"wiener","password":"peter", "$where":"0"}{"username":"wiener","password":"peter", "$where":"1"}`

### Preventing NoSQL injection <a href="#preventing-nosql-injection" id="preventing-nosql-injection"></a>

The appropriate way to prevent NoSQL injection attacks depends on the specific NoSQL technology in use. As such, we recommend reading the security documentation for your NoSQL database of choice. That said, the following broad guidelines will also help:

* Sanitize and validate user input, using an allowlist of accepted characters.
* Insert user input using parameterized queries instead of concatenating user input directly into the query.
* To prevent operator injection, apply an allowlist of accepted keys.

### Labs

{% embed url="<https://portswigger.net/web-security/nosql-injection>" %}
