Mongection is a simple NodeJS web application that simulates a login page. It has both /register
and /login
routes that, by communicating with a MongoDB, enable users to register and enter into a generic system.
Injection flaws, such as SQL, NoSQL, OS, and LDAP injection, occur when untrusted data is sent to an interpreter as part of a command or query. The attacker’s hostile data can trick the interpreter into executing unintended commands or accessing data without proper authorization.
The main goal of this project is to discuss how NoSQL Injection vulnerabilities can be exploited and to encourage developers to send Pull Requests to secDevLabs on how they would mitigate these flaws.
To start this intentionally insecure application, you will need Docker and Docker Compose. After forking secDevLabs, you must type the following commands to start:
cd secDevLabs/owasp-top10-2021-apps/a3/mongection
make install
Then simply visit localhost:10001, as exemplified below:
To properly understand how this application works, you can follow these simple steps:
- Register a new user via front-end.
- Login as this user via front-end.
- Register another user now using command line:
curl -X POST http://localhost:10001/register -H "Content-Type: application/json" --data '{"name":"bob", "email":"[email protected]", "password":"bobisboss"}'
- Login as this second user now using command line:
curl -X POST http://localhost:10001/login -H "Content-Type: application/json" --data '{"email":"[email protected]", "password":"bobisboss"}'
Now that you know the purpose of this app, what could go wrong? The following section describes how an attacker could identify and eventually find sensitive information about the app or its users. We encourage you to follow these steps and try to reproduce them on your own to better understand the attack vector! 😜
After reviewing db.js file, it was possible to see that some input from users is concatenated with NoSQL queries, as shown in the following code snippets:
const existUser = await User.findOne({ email: email });
const existsUser = await User.find({
$and: [{ email: email }, { password: password }],
});
As no validation is being made on these variables, injected queries may be successfully executed in MongoDB. Some directives like $ne
or $gt
, if successfully injected, could bypass API authentication.
An attacker could create a malicious query such as {"$ne":""}
and pass it to email and password fields. Since $ne
is the not equals condition in MongoDB, this is querying all the entries in the logins collection where both username
and password
are not equal to "" (empty).
Using curl
on CLI interface, the malicious payload could be sent as shown bellow:
curl -X 'POST' 'http://localhost:10001/login' -H "Content-Type: application/json" --data '{"email": {"$ne":""}, "password": {"$ne":""}}'
The application will return the first user that MongoDB finds with a "Hello, Welcome Again!" message, demonstrating that authentication has been bypassed. There must be at least one user already registered in the database to recieve this message.
The same result could be reached if the attacker sent a payload using $gt
(greater than) directive. The following query will search for entries with both username
and password
fields greater than "" (empty).
curl -X 'POST' 'http://localhost:10001/login' -H "Content-Type: application/json" --data '{"email": {"$gt": ""}, "password": {"$gt": ""}}'
Another possible malicious payload could use $in
directive. The following query will iterate through every element of the given array and try each value listed for the username
field. Also, {"$gt":""}
will guarantee the password
field is not evaluated.
curl -X 'POST' 'http://localhost:10001/login' -H "Content-Type: application/json" --data '{"email": {"$in":["[email protected]", "root@example", "[email protected]", "bob"]}, "password": {"$gt":""}}'
How could you now mitigate this vulnerability? After your code modification, an attacker should not be able to:
- Run NoSQL queries in the database.
[Spoiler alert] To understand how this vulnerability can be mitigated, check these pull requests!
We encourage you to contribute to SecDevLabs! Please check out the Contributing to SecDevLabs section for guidelines on how to proceed! 🎉