Exploiting NoSQL operator injection to extract data

Exploiting NoSQL operator injection to extract data

Even if the original query doesn't use any operators that enable you to run arbitrary JavaScript, you may be able to inject one of these operators yourself. You can then use boolean conditions to determine whether the application executes any JavaScript that you inject via this operator.

Injecting operators in MongoDB

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"}

If there is a difference between the responses, this may indicate that the JavaScript expression in the $where clause is being evaluated.

Extracting field names

If you have injected an operator that enables you to run JavaScript, you may be able to use the keys() method to extract the name of data fields. For example, you could submit the following payload:

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

This inspects the first data field in the user object and returns the first character of the field name. This enables you to extract the field name character by character.

Exfiltrating data using operators

Alternatively, you may be able to extract data using operators that don't enable you to run JavaScript. For example, you may be able to use the $regex operator to extract data character by character.

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

{"username":"myuser","password":"mypass"}

You could start by testing whether the $regex operator is processed as follows:

{"username":"admin","password":{"$regex":"^.*"}}

If the response to this request is different to the one you receive when you submit an incorrect password, this indicates that the application may be vulnerable. You can use the $regex operator to extract data character by character. For example, the following payload checks whether the password begins with an a:

{"username":"admin","password":{"$regex":"^a*"}}

Lab

The user lookup functionality for this lab is powered by a MongoDB NoSQL database. It is vulnerable to NoSQL injection.

To solve the lab, log in as carlos.

To solve the lab, you'll first need to exfiltrate the value of the password reset token for the user carlos.

Steps

<Todo>

Last updated