NoSQL injection

What is NoSQL injection?

NoSQL injection is a vulnerability that lets a malicious hacker introduce (inject) undesired code into database queries executed by NoSQL databases.


Severity: very severe
Prevalence: discovered rarely
Scope: may appear in NoSQL databases
Technical impact: database access
Worst-case consequences: full control over the application
Quick fix: fully dependent on the type of NoSQL database

What is NoSQL?

The term NoSQL (non-SQL or not only SQL) is used to describe non-relational databases in general and may refer to many different types of databases and data models, including key-value, key-document, column-family, and graph databases. NoSQL databases have rapidly gained popularity in recent years, with mainstream products such as MongoDB, Apache Cassandra, Apache HBase, Apache CouchDB, Neo4j, RavenDB, Redis, OrientDB, DynamoDB, HyperTable, Google Cloud Datastore, and many more.

NoSQL database engines use different data structures than relational databases and while they usually do not support SQL statements or SQL queries, they all provide ways for users to execute queries. Unlike with SQL databases, there is no common query language or syntax, so the query format depends on the specific database product and the implementation details of the web application or API. This means your queries will vary depending not only on the database but also on the programming language (e.g. Python, PHP, Node.js, etc.) and framework (e.g. Spring). Even so, most NoSQL queries are based on JSON, and they will often include user input. This means that – as always with unsanitized user inputs – NoSQL databases can also be vulnerable to injection attacks.

How does NoSQL injection work?

NoSQL injections don’t rely on a common query language, so a given injection vulnerability affects only one specific NoSQL database type. Apart from that, NoSQL injection attacks are similar to traditional SQL injection attacks – the attacker provides a malicious payload in user input, such as forms or HTTP requests, and if that input is delivered to the NoSQL database without sanitization, it may cause the database to execute commands supplied by the attacker.

Examples of NoSQL injection

To understand how a NoSQL query is constructed and where it may be vulnerable to an injection attack, we will focus on MongoDB as the most popular NoSQL database, accessing it using PHP. Here is a simple example that accesses a MongoDB database to perform authentication:

$username = $_POST['username'];
$password = $_POST['password'];
$connection = new MongoDB\Client('mongodb://localhost:27017');
if($connection) {
	$db = $connection->test;
	$users = $db->users;
	$query = array(
		"user" => $username,
		"password" => $password
	);
	$req = $users->findOne($query);
}

As you can see, the username and password parameters used for authentication are taken from a POST request and then directly inserted into the query. Similar to other types of injection, this allows a malicious user to enter a NoSQL injection payload that provides unauthenticated access.

To perform a successful MongoDB injection, it could be enough to supply the following malicious input data in a POST request:

username[$eq]=admin&password[$ne]=foo

The [$ne] query operator means not equal, so the resulting query will find the first record where the username is admin and the password is not foo. If such code is used for authentication and the admin user exists, the attacker will be logged in as that user.

Other MongoDB operators can be abused in a similar fashion, for example, [$lt] and [$gt] as well as [$regex]. Using regular expressions in the above scenario, attackers might even be able to enumerate all users by trying various combinations in sequence and evaluating the results.

Advanced attacks and JavaScript injections

MongoDB queries commonly include the $where operator, which introduces possibilities of serious NoSQL attacks that include JavaScript objects. For example, a developer might want to use the $where operator in the following way to access a record for a particular user:

$query = array('$where' => 'this.name === \''.$name.'\'');

In this case, an attacker could use the following empty string comparison trick by injecting into $name:

'; return '' == '

As a result, the query will become:

"$where": "this.name === ''; return '' == ''"

Because the result is always true, the attacker will receive the entire list of users.

The $where operator is actually evaluated as JavaScript code, so the attacker could also pass a parameter with a malicious string that includes arbitrary JavaScript, for example:

'; while(true){}'

This example creates an endless loop that results in a denial of service attack.

Potential consequences of a NoSQL injection attack

NoSQL injection attack consequences depend on the database type and the way database communication is implemented. The attacker might bypass authentication, extract data, modify data, or even gain complete control over the web application. As a result, they may even be able to access the underlying operating system and gain control over the web server.

How to detect NoSQL injection vulnerabilities?

The best way to detect NoSQL injection vulnerabilities varies depending on whether they are already known or unknown.

  • If you only use commercial or open-source software and do not develop software of your own, it may be enough to identify the exact version of the system or application you are using. If the identified version is susceptible to NoSQL injections, you can assume that your software is vulnerable. You can identify the version manually or use a suitable security tool, such as a software composition analysis (SCA) solution.
  • If you develop your own software or want the ability to potentially find previously unknown NoSQL injection vulnerabilities (zero-days) in known applications, you must be able to successfully exploit the NoSQL injection vulnerability to be certain that it exists. This requires either performing manual pentesting with the help of security researchers or using a web application security tool that can use automation to exploit web vulnerabilities. Examples of such tools are Invicti and Acunetix by Invicti, which can discover NoSQL injections in several popular products, including MongoDB and others. We recommend using this method even for known vulnerabilities.

How to prevent NoSQL injection vulnerabilities

To prevent NoSQL injections, you must follow general cybersecurity best practices and always treat user input as untrusted. Here are some general user input validation tips for all NoSQL databases:

  • Use a suitable sanitization library, such as mongo-sanitize or mongoose for MongoDB.
  • If you can’t find a library for your environment, cast user input to the expected type. For example, cast usernames and passwords to strings.
  • In the case of MongoDB, never directly combine the where, mapReduce, or group operators with user input because they could allow attackers to inject JavaScript, making them especially dangerous. For extra safety, set javascriptEnabled to false in mongod.conf whenever possible.

How to mitigate NoSQL injection attacks?

Unlike many other web vulnerabilities, NoSQL injections can be caused not only by insecure web application code but also by vulnerabilities in NoSQL databases themselves. To improve mitigation, you should always use the latest versions of NoSQL databases, especially since some products, including MongoDB, were in the past known to have serious vulnerabilities.

Note that since NoSQL databases are a much more recent technology compared to SQL databases and there are also many different types to choose from, the potential for developer error is much higher. To minimize risk, make sure to always follow the principle of least privilege by running your application with the lowest privileges possible. That way, even a successful attack will not provide access to other server-side resources.

Frequently asked questions

What is NoSQL injection?

NoSQL injection is a vulnerability that lets a malicious hacker introduce (inject) undesired code into database queries executed by NoSQL databases such as MongoDB, Cassandra, Neo4j, Redis, and more.

 

Read our blog article about NoSQL injections.

How dangerous are NoSQL injections?

NoSQL injections may allow the attacker to bypass authentication, extract data, modify data, or even gain complete control over the web application. As a result, malicious actors may even be able to access the underlying operating system and gain control over the web server.

 

Read an interesting post on the Shodan blog about the security of NoSQL databases.

How to prevent NoSQL injections?

To prevent NoSQL injections, follow general cybersecurity best practices and always treat user input as untrusted. Use input sanitization libraries available for many NoSQL products, including MongoDB.

 

Learn about the importance of input validation, not just for NoSQL injections.

ClassificationID
CAPEC676
CWE943
WASC19
OWASP 2021A3

Related blog posts


Written by: Tomasz Andrzej Nidecki, reviewed by: Aleksei Tiurin