noSQL Injection

In previous posts I have talked about SQL injections. It is usually the first example of computer security that is given to a student: ” ´ or 1 = 1 — a “

However, this is only useful for servers that use relational databases, such as MySQL, MSSQL, Oracle. In the last decade another type of database has appeared: non-relational databases, such as Couch or MongoDB.

This type of database is used to store a large amount of unrelated data, data that do not fit into the typical tabular model of SQL databases, such as images, videos, social media, and so on.

The queries that are made to this type of non-SQL databases are very different from the SQL queries. Therefore, trying to put a quotation mark in a parameter will not work in these cases. However, this does not imply that they are free of injections. In this post I will show how and why noSQL injection works through proofs of concept. All examples are based on the book “The Hacker Playbook 3”.

Simple NoSQL Injection

In order to perform a noSQL injection, it is necessary to send a query to the server in the form of JSON, and that we can manipulate it using NoSQL comparators.

The equivalence of comparators in noSQL is as follows: > is $gt, < is $lt, >= is $gte, y <= is $lte.

The equivalent to [ ` or 1 = 1 — a ] of SQL would be [ {“$gt”:””} ]. It means that the $gt operator is greater than NULL. As anything is greater than NULL, the query always returns TRUE. It will be better understood in the following example:

If we try to login to a server that uses non-relational databases, the request will contain a JSON similar to {“username”: “admin”, “password”: “admin”}.

noSQL Injection

On the server, a query will be sent to the database similar to this one:

db.collection(collection).find({“username”:username,”password”:password}).limit(1)…

The injection consists of inserting the payload {“$gt”:””} as a password, a sentence that always returns TRUE, allowing direct access to the admin user without knowing his password:

If you do not know the name of the administrator user, it is still possible to log in with his account. The thing to do is to indicate in username the payload “username”:{“$gt”: “aaa”}. That way, you will access with the first user of the table whose name is greater than “aaa”. You will have to test name by name until you find the administrator user account:

Other considerations

New frameworks and languages can make nonSQL injection opportunities arise. For example, Node.js, a javascript-based server model that has become very popular recently, has a module called qs that allows you to convert the parameters of HTTP requests into JSON objects.

A request of the style username[value]=admin&password[value]=admin would be converted to {“username”:{“value”: “admin”}, “password”:{“value”: “admin”}}.

If the programmer has not taken into account this automatic conversion and only validates JSON requests, we can get a noSQL injection by sending an http request. Just modify the request that was originally sent in the login (username=admin&password=admin&submit=login) for the following:

You can find more examples of NoSQL injection on the OWASP page.

Lethani

4.5/5 - (216 votes)

4 thoughts on “noSQL Injection”

Leave a comment