NoSQL Injection (Part 1 of the SQL Series)

Alex Archondakis

Managing Consultants

Alex is one of our managing consultants here at Pentest People. Focusing mainly on web application penetration testing. Alex has spoken at many key events while with us, including BSides London and even DSS ITSEC Latvia.

NoSQL Injection (Part 1 of the SQL Series)

All developers are aware of MySQL Injection (or they should be!) but what about NoSQL Injection?

There are not too many vulnerabilities relating to NoSQL databases (such as NoSQL injection) at the moment, but as the technology is growing and becoming more and more used, the number of vulnerabilities is going to increase.

According to nosql-database.org  there are currently over 225 types of NoSQL database options such as: Cassandra, DynamoDB, MongoDB, Cloud Datastore. Each of these solutions, along with the many not listed here may have their own vulnerabilities.

(N.B There is an argument that the term NoSQL no longer just stands for “No SQL” but “Not Only SQL”.)

Currently, the most widely used NoSQL database is MongoDB, which does have a few vulnerabilities.

A pentest can help you keep track of these vulnerabilities (shameless up-sell right there!) but so can checking pages such as nosql-database.org. There is one thing you as a developer can do right now to help protect your application when using a NoSQL database. And that is to protect yourself from NoSQL injection.

NoSQL injection is a real issue. Unlike SQL Injection, a NoSQL injection attack can take place on the application layer or in the actual NoSQL database.

Typically the attack will happen on the application layer where a string is parsed, evaluated or concatenated into the NoSQL API call.

Let’s look at the following example of a PHP MongoDB login script:

$userName = $_POST[‘user’];
$password = $_POST[‘password’];
$user = $collection->findOne(
[
'user' => ‘$userName’,
'password' => ‘$password’,
]
);

Now, with MongoDB ‘$ne’ means not equals so in this case if an attacker submits the username and password as ‘{“$ne”: null}’ the code will look like this:

$userName = $_POST[‘user’];
$password = $_POST[‘password’];
$user = $collection->findOne(
[
'user' => ‘{"$ne": null}’,
'password' => ‘{"$ne": null}’,
]
);

This code will now return the first user found.

Are more serious example of NoSql injection is when a special query operators are used, such as ‘$where’ or ‘$exists’ (as well as others). As you know these are also seen as php variables, this may make it possible for attackers to insert code into the query. One way to do this is through HTTP Parameter Pollution (we will go into this in another post).

The PHP documentation for MongoDB warns against this:

Please make sure that for all special query operators (starting with $) you use single quotes so that PHP doesn’t try to replace “$exists” with the value of the variable $exists.

With MongoDB you can use something like mongo-sanitize to guard against potential injection attacks. Of course you should still validate your user input yourself before relying on a third party.  

But What if You Are Not Using MongoDB?

Again the answer is simple, validate and sanitise your data. PHP has many ways to check user input, for example if you are requesting and expecting a user to submit an email address you could use Sanitize Filters to handle this for you as well as other methods.

If you are using DynamoDB where injection does not look to be easy to achieve, it does not mean that you can simply store the user input without any validation. This stored unvalidated/unsanatised data could lead to a Second Order Sql Injection.

Second Order Sql Injection is a vulnerability that occurs when submitted values are stored in a database and used at another function in the application. Again we can talk about this in more detail at another time.

Let’s think about how a NoSQL database often work alongside SQL databases. So if a user manages to store a ‘1=1’ into a NoSQL table, and that item is pulled back into the application and processed by SQL this can be a big issue.

Keep in mind as well that NoSQL databases are often used to store large amounts of data quickly that can come in from third party. How do you know that the third party API feed or CSV has not been compromised itself? The answer is you don’t. Therefor again do not rely on a third party to make sure your application is safe. Validate! Validate! Validate!

SQL injection is still one of the most common vulnerabilities we come across at Pentest People. With NoSQL databases becoming more and more popular, the number of NoSQL injection attacks is also likely to rise. Because of this, it is vital that you as a developer do not forget the basics when it comes with security. Always sanitise and validate your user input data. Likewise if user data is going to be used in another part of the application make sure you validate the output data from one part of the application before it is used in another.

Interested about Web Application Services? Find out more here.

Video/Audio Transcript