Project Description

What is NoSQL Injection?

NoSQL databases are an alternative to databases that use SQL. Instead of storing data in tables, these databases store data in objects called documents, which are organized into collections. There is no standard query language for NoSQL databases, hence the name. Instead, each NoSQL platform uses its syntax and protocol.

The simplest form of a NoSQL database is the Key-value store, where each key is mapped to a value containing arbitrary data. Around 40% of the NoSQL databases are Key-Value Stores.

NoSQL databases symbolize data using key/value mappings and do not depend on a fixed schema such as a traditional database table. Keys and values can be arbitrarily specified, and the value format is typically not relevant to the data store. An additional feature of key/ value storage is that a value may be a data structure, permitting hierarchical storage, unlike the flat data structure inside a database schema.

NoSQL promoters claim this has several benefits, mainly in managing massive data sets, where the data store’s hierarchical structure can be optimized as required to decrease the overhead in retrieving data sets. In these instances, a traditional database may require complex cross-referencing of tables to retrieve information on behalf of an application. From a web application security perspective, the critical concern is how the application queries data because this defines what ways of injection are possible. In the case of SQL injection, the SQL language is considerably identical across different database products. NoSQL, by difference, is a name given to a disparate range of data stores, all with their behaviors. They do not all use a single query language.

The following section describes one example of a vulnerability in NoSQL databases derived from a real-world application.

 

How is it exploited?

MongoDB is currently one of the most popular NoSQL databases. It stores data using syntax similar to JSON, BSON (Binary JSON), and includes a secure BSON query assembly tool. Unserialized JSON and Javascript expressions are permitted in several alternative query parameters like $where.

Consider the following authentication bypass database query:

$query = array("user" => $_POST["username"], "password" => $_POST["password"]);

The attacker can send the following injected string in the request:

username[$ne] = 1 & password[$ne] = 1

It will get translated into an array of arrays which, when sent as a MongoDB query to the database, will find all users where the username and password are not equal to 1. This will then allow the attacker to bypass the authentication.

A typical application will expect to receive the username and password fields either as a standard HTML FORM submit or through an AJAX call where the request sends these fields as a JSON content type.

To authenticate the user, a typical POST login route and matching the request sent from the browser to the database would look similar to the following:
app.post(‘/login‘, function(req, res) {
User.findOne({username: req.body.username, password: req.body.password}, function (err, user) {
// Rest of the code
});
});

The User model runs a query to the MongoDB database to match the username and password fields in the code above. They are populated in the req.body object as first citizens JavaScript properties. However, the username and password fields are not validated to ensure that they are strings.

If a malicious user takes advantage of this sort of authentication matching logic, they can exploit MongoDB’s operators to return a valid user’s object. This can be performed by sending the following JSON data as the login POST request:

username[$ne] = 1 & password[$ne] = 1
This works because the req.body.username will be set to the object {“$gt”: “”} which is a valid MongoDB operator to match any documents where the username field is not empty.

Consequences

Like SQL Injections, NoSQL Injections so impact the fundamentals of cybersecurity known as Confidentiality, Integrity, and Availability. 

DDoS attacks can be orchestrated, servers can be taken over, confidential user information can be extracted, etc. Larger websites often use a NoSQL database, a newer variety of databases that relax some of the constraints of the traditional SQL database to achieve greater scalability.

When it comes to privacy and data leakage, attackers can provide a RegEx value that will match many records in order to pull out information from the MongoDB server.

 

Why is the app vulnerable?

The root cause of injection vulnerabilities stems from a lack of input sanitization, meaning that when a user submits input, it is not being adequately checked for maliciousness. That input is subsequently used in a dynamic nature to either run a query, execute a command, or otherwise interact with the vulnerable system to cause harm.

Mitigation 

To prevent NoSQL injections one needs to validate the user input or escape it properly. Some Node.js libraries like sequelize ORM provide prepared statements for queries.

A very first and essential step is to validate user input with regards to the following rules to confirm that the expected type being received in the request is valid:

  •  Validate the length and type of the data
  •  Validate and sanitize the input to an expected type

To mitigate the NoSQL injection vulnerability, a simple fix to the code should be implemented – casting the username and password fields to a string.

app.post('/login', function(req, res) {User.findOne({username: req.body.username, password: req.body.password}, function (err, user) {
// Rest of the code
});
});

 

General guidelines to avoid and mitigate NoSQL injection attacks:

  • Sanitizing and validating user input – do not allow user originating input as is. Always validate, and filter to match the allowed and expected data.
  • Prepared statements – familiarize yourself with traditional SQL methodologies, and secure the data passed to the queries through prepared statements.
  • Follow the principle of Least Privilege regarding application accounts to minimize damage if a NoSQL injection attack is successful.
  • Do not use insecure JavaScript functions to parse user input, such as: eval(), setTimeout(), setInterval(), and Function()
  • Implementing code best practices: The security guidelines and manuals for NoSQL databases must be read carefully and thoroughly. Developers must understand the language used to ensure that vulnerable constructs are avoided.