How to Prevent No-SQL Injection in Node.js

This article explains what is No-SQL Injection attack, how usually attackers make it and, how we can prevent it.

The attack is called SQL Injection but the same concept applies to No-SQL databases too.

SQL or No-SQL Injection

Why it is important to know (No-)SQL Injection?

By taking a look at HackerOne Top Ten Vulnerabilities we can quickly understand the importance of SQL Injection and why we should care about it.

SQL Injection Rank in HackerOne Bonty(Rank 7th)
SQL Injection Bounty ranking

There are two main reasons that make (No-)SQL Injection very tempting for attackers:

  • Abundance of (No-)SQL Injection vulnerabilities
  • Database is a very attractive target since it contains critical data

What is a (No-)SQL Injection?

What we do on the backend side is mostly based on the data that comes from the request(user). An example is when a user does Login. So we have to get the email of the user and check if it exists and matches the password. We store data in the database and as a result, we have to make a query to the database to find the email. So the Email that the User gave to us is part of the Query. This is where the attacker can do some tricks to extract or manipulate data by giving us something other than a simple Email. This is how an SQL Injection is done.

The Intention of (No-)SQL Injection is access to the database or parts of the database that it should not have.

Examples of No-SQL Injection Attacks

No-SQL Injection(MongoDB)

In the first example, we want to work on Express app that uses MongoDB Native Driver. Why anyone might want to use the native driver? Because in terms of performance, it is the best!(As you can see in the chart below)

Mongoose vs MongoDB Driver

https://medium.com/media/78d7dba029c2ab0834e018eb6c8afca9/href

We have a login route that does not have Validation and passes email and password directly to MongoDB Driver.

First, let’s create a user with the register route and check the Login logic:

Create a Valid User with Password and Email

Now we can login with this valid user that we just created but If we use an invalid user, obviously we cannot Login:

Failed Login with User: Attacker@gmail.com

How to do the No-SQL Injection

We know that MongoDB supports regex with the operator $regex so we can pass this operator instead of a String and use a regex that accepts anything ,*:

https://medium.com/media/90572a046b6fb82312f90fb6c8d4de9d/href

As you can see in the picture we were able to Login without having a user:

Using Regex Operator to Bypass MongoDB findOne

This was done with MongoDB native driver. Using other ODM’s like Mongoose will not solve this issue:

https://medium.com/media/368004925d8e5895af2f067d8acf3ebb/href

Mongoose is behaving the way we expect. We can bypass login by using $regex .

Bypassing Login when using Mongoose

Is it the responsibility of ODM to Prevent (No-)SQL Injections?

I was mad at my ODM(Mongoose) at first but after a little bit of thinking I realized that Mongoose or Prisma are just libraries for easier database interactions. How could they distinguish that it is you that wants to use the regex or an attacker?

Long story short: It is not the responsibility of ODM or ORM and even if some of them are doing it you cannot be so sure that your app is safe against Injections(Sequalize Security Issue that resulted in SQL Injection).

How to Prevent No-SQL Injection

Avoid Passing Request Objects Directly To ODM or ORM Functions

The worst thing we can do is to pass something like req.body or req.query directly to our ODM/ORM functions:

const user = await collection.findOne(req.body); // Bad Practice

The least we can do is to use the specific fields

const user = await collection.findOne({ userId: req.body.id });

Use Input Validation

Using something like Zod, Yup, and other options.

Example of validating with Zod:

const loginValidator = z.object({
email: z.string().email(),
password: z.string()
});

By using objectStrict it will return an error if someone tries to add extra fields.

https://medium.com/media/9143b7347cd1625ad72aa2b54e8e8e5c/href

Now sending a request like this will result in an error:

Sending Extra Field in the Body of Request

Sanitize User Inputs and Filters

Hopefully, Mongoose 6 introduced a sanitizer that you can use: “Sanitizes query filters against query selector injection attacks by wrapping any nested objects that have a property whose name starts with $ in a $eq.”

const obj = { username: 'val', pwd: { $ne: null } };
sanitizeFilter(obj);
obj; // { username: 'val', pwd: { $eq: { $ne: null } } });

By wrapping phrases in $eq it prevents injections that are trying to get more data.

If we are not using Mongoose there are other options to consider:

express-mongo-sanitize is a library that checks req.body, req.params, req.query and req.headers for prohibited characters.

Another option is mongo-sanitize that strip out any keys which start with $ in the input.

Conclusion

We know that (No-)SQL Injection is important and common since the target is the database. We need to do some simple steps to prevent this attack: 1- Avoid passing req objects directly, use strong validation, and in the end use sanitizers.

These other articles might be also interesting for you:

Level Up Coding

Thanks for being a part of our community! Before you go:

🚀👉 Join the Level Up talent collective and find an amazing job


How to Prevent No-SQL Injection in Node.js was originally published in Level Up Coding on Medium, where people are continuing the conversation by highlighting and responding to this story.


This content originally appeared on Level Up Coding - Medium and was authored by Poorshad Shaddel

This article explains what is No-SQL Injection attack, how usually attackers make it and, how we can prevent it.

The attack is called SQL Injection but the same concept applies to No-SQL databases too.

SQL or No-SQL Injection

Why it is important to know (No-)SQL Injection?

By taking a look at HackerOne Top Ten Vulnerabilities we can quickly understand the importance of SQL Injection and why we should care about it.

SQL Injection Rank in HackerOne Bonty(Rank 7th)
SQL Injection Bounty ranking

There are two main reasons that make (No-)SQL Injection very tempting for attackers:

  • Abundance of (No-)SQL Injection vulnerabilities
  • Database is a very attractive target since it contains critical data

What is a (No-)SQL Injection?

What we do on the backend side is mostly based on the data that comes from the request(user). An example is when a user does Login. So we have to get the email of the user and check if it exists and matches the password. We store data in the database and as a result, we have to make a query to the database to find the email. So the Email that the User gave to us is part of the Query. This is where the attacker can do some tricks to extract or manipulate data by giving us something other than a simple Email. This is how an SQL Injection is done.

The Intention of (No-)SQL Injection is access to the database or parts of the database that it should not have.

Examples of No-SQL Injection Attacks

No-SQL Injection(MongoDB)

In the first example, we want to work on Express app that uses MongoDB Native Driver. Why anyone might want to use the native driver? Because in terms of performance, it is the best!(As you can see in the chart below)

Mongoose vs MongoDB Driver

We have a login route that does not have Validation and passes email and password directly to MongoDB Driver.

First, let’s create a user with the register route and check the Login logic:

Create a Valid User with Password and Email

Now we can login with this valid user that we just created but If we use an invalid user, obviously we cannot Login:

Failed Login with User: Attacker@gmail.com

How to do the No-SQL Injection

We know that MongoDB supports regex with the operator $regex so we can pass this operator instead of a String and use a regex that accepts anything ,*:

As you can see in the picture we were able to Login without having a user:

Using Regex Operator to Bypass MongoDB findOne

This was done with MongoDB native driver. Using other ODM’s like Mongoose will not solve this issue:

Mongoose is behaving the way we expect. We can bypass login by using $regex .

Bypassing Login when using Mongoose

Is it the responsibility of ODM to Prevent (No-)SQL Injections?

I was mad at my ODM(Mongoose) at first but after a little bit of thinking I realized that Mongoose or Prisma are just libraries for easier database interactions. How could they distinguish that it is you that wants to use the regex or an attacker?

Long story short: It is not the responsibility of ODM or ORM and even if some of them are doing it you cannot be so sure that your app is safe against Injections(Sequalize Security Issue that resulted in SQL Injection).

How to Prevent No-SQL Injection

Avoid Passing Request Objects Directly To ODM or ORM Functions

The worst thing we can do is to pass something like req.body or req.query directly to our ODM/ORM functions:

const user = await collection.findOne(req.body); // Bad Practice

The least we can do is to use the specific fields

const user = await collection.findOne({ userId: req.body.id });

Use Input Validation

Using something like Zod, Yup, and other options.

Example of validating with Zod:

const loginValidator = z.object({
email: z.string().email(),
password: z.string()
});

By using objectStrict it will return an error if someone tries to add extra fields.

Now sending a request like this will result in an error:

Sending Extra Field in the Body of Request

Sanitize User Inputs and Filters

Hopefully, Mongoose 6 introduced a sanitizer that you can use: “Sanitizes query filters against query selector injection attacks by wrapping any nested objects that have a property whose name starts with $ in a $eq.”

const obj = { username: 'val', pwd: { $ne: null } };
sanitizeFilter(obj);
obj; // { username: 'val', pwd: { $eq: { $ne: null } } });

By wrapping phrases in $eq it prevents injections that are trying to get more data.

If we are not using Mongoose there are other options to consider:

express-mongo-sanitize is a library that checks req.body, req.params, req.query and req.headers for prohibited characters.

Another option is mongo-sanitize that strip out any keys which start with $ in the input.

Conclusion

We know that (No-)SQL Injection is important and common since the target is the database. We need to do some simple steps to prevent this attack: 1- Avoid passing req objects directly, use strong validation, and in the end use sanitizers.

These other articles might be also interesting for you:

Level Up Coding

Thanks for being a part of our community! Before you go:

🚀👉 Join the Level Up talent collective and find an amazing job


How to Prevent No-SQL Injection in Node.js was originally published in Level Up Coding on Medium, where people are continuing the conversation by highlighting and responding to this story.


This content originally appeared on Level Up Coding - Medium and was authored by Poorshad Shaddel


Print Share Comment Cite Upload Translate Updates
APA

Poorshad Shaddel | Sciencx (2023-04-20T16:32:14+00:00) How to Prevent No-SQL Injection in Node.js. Retrieved from https://www.scien.cx/2023/04/20/how-to-prevent-no-sql-injection-in-node-js/

MLA
" » How to Prevent No-SQL Injection in Node.js." Poorshad Shaddel | Sciencx - Thursday April 20, 2023, https://www.scien.cx/2023/04/20/how-to-prevent-no-sql-injection-in-node-js/
HARVARD
Poorshad Shaddel | Sciencx Thursday April 20, 2023 » How to Prevent No-SQL Injection in Node.js., viewed ,<https://www.scien.cx/2023/04/20/how-to-prevent-no-sql-injection-in-node-js/>
VANCOUVER
Poorshad Shaddel | Sciencx - » How to Prevent No-SQL Injection in Node.js. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2023/04/20/how-to-prevent-no-sql-injection-in-node-js/
CHICAGO
" » How to Prevent No-SQL Injection in Node.js." Poorshad Shaddel | Sciencx - Accessed . https://www.scien.cx/2023/04/20/how-to-prevent-no-sql-injection-in-node-js/
IEEE
" » How to Prevent No-SQL Injection in Node.js." Poorshad Shaddel | Sciencx [Online]. Available: https://www.scien.cx/2023/04/20/how-to-prevent-no-sql-injection-in-node-js/. [Accessed: ]
rf:citation
» How to Prevent No-SQL Injection in Node.js | Poorshad Shaddel | Sciencx | https://www.scien.cx/2023/04/20/how-to-prevent-no-sql-injection-in-node-js/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.