What is NoSQL injection?
Injection attacks are considered some of the most dangerous types of vulnerabilities in existence. According to the OWASP Top Ten List of web application vulnerabilities, injection is the most common and dangerous type. On the 2019 CWE Top 25 Most Dangerous Software Errors list, poor input sanitization (which enables injection attacks) took the number three spot.
Injection vulnerabilities exist in a variety of different contexts, but they all boil down to the same issue. Several different languages, whether SQL, LDAP or the Linux shell, mix code and data together in commands.
11 courses, 8+ hours of training
In many cases, the data is supplied by untrusted users. While the language typically differentiates code from data, this differentiation usually amounts to a pair of single or double quotes. If a user can close a set of quotes (e.g., by including one in their input), they can get part of their data interpreted as code and executed by the program.
This is why poor input sanitization is the primary enabler of injection attacks. If certain dangerous characters (like quotes) are disallowed or escaped in user-supplied input, they can’t be used to close the quotes that delineate the user’s input as data. However, many developers fail to properly sanitize user input, leaving their applications open to attack.
NoSQL injection attacks
SQL injection is a well-known vulnerability. SQL is designed to enable queries to be performed against a database, extracting data based upon logical operators. Since these queries often include user-provided input, they can be vulnerable to attack if input sanitization is not properly performed.
NoSQL databases do not use SQL to perform queries. However, this does not make them invulnerable to injection attacks. Since queries still include user-provided data, a failure to properly sanitize this user input can still be dangerous.
Introduction to NoSQL
NoSQL (aka non-relational) databases do not use SQL for queries. A variety of different NoSQL database types exist, such as:
- Key-Value
- Key-Document
- Column-Family
- Graph
NoSQL was designed in response to the move to agile design methodologies. Relational (SQL) databases require schemas to be defined in advance and do not allow them to be updated once data is already in the database. Adding new fields requires migrating the database to a new schema, which can be time-consuming.
NoSQL supports dynamic schema definitions. Data can be added without a clear schema definition, enabling the database to operate in accordance with rapid agile development cycles. Unlike relational databases, NoSQL can also easily scale horizontally with automatic sharding built in. This ensures that the development team is not limited by the hardware that is available or forced to manually implement sharding.
Attacking NoSQL
While NoSQL databases like MongoDB do not use SQL for queries, they still do queries based upon user input. This means that they are still vulnerable to injection attacks if the developer does not properly perform input sanitization.
The primary difference between SQL and NoSQL injection is the grammar and syntax of the query. Attempting to perform NoSQL injection with an SQL injection attack string is unlikely to be successful. NoSQL databases do not have a standardized language. However, the syntax of their languages is very similar (since they’re designed to do the same thing).
One application of NoSQL injection is to attack web applications built on the MEAN (MongoDB, Express, Angular and Node) stack. When passing data, MEAN applications use JSON, which is the same thing used by MongoDB. Injection of JSON code into a MEAN application can enable injection attacks against a MongoDB database.
For example, the screenshot above (from NullSweep) shows an application that is vulnerable to NoSQL injection. From a request, the code pulls a username and password and places it into a MongoDB query without performing any input sanitization. By passing the JSON {"username":"myaccount","password":{"$ne": 1}} , an attacker could authenticate to the service without a password.
Beyond NoSQL injection
MongoDB and other NoSQL databases are commonly used in web applications. For example, a web page may request user account credentials in a web form, store authentication information in a MongoDB database, and perform credential checks using JavaScript.
The tight integration of MongoDB into JavaScript and other programming languages means that NoSQL injection attacks can be used to perform attacks at other levels. For example, Mongo will support evaluation of JavaScript code if it is placed in a where clause or passed into a group or mapReduce function. A NoSQL injection attack including JavaScript code (properly quoted and so on) will enable execution of that code within the web application.
Protecting against NoSQL injection attacks
NoSQL injection attacks are very similar to SQL injection: they take advantage of poor sanitization of user input when building database queries. This means that the same tools for protecting against SQL injection attacks also work for NoSQL, such as:
- Never building queries from strings
- Using typed inputs
- Using an input sanitization library to escape dangerous characters
- Minimizing privileges on public-facing applications
However, there are also additional steps to take when protecting NoSQL databases. For example, JavaScript evaluation can be disabled in MongoDB, decreasing the potential impact of an injection attack. Reading the manual and security guidance for a particular NoSQL database is always a good idea.
The bottom line on NoSQL injection
NoSQL databases are still databases, meaning that it is often important to perform queries using user-provided data. As with SQL databases, it is important to ensure that information is properly sanitized before using it in a query to minimize an application’s vulnerability to injection attacks.
Sources
- Foreword, OWASP
- 2019 CWE Top 25 Most Dangerous Software Errors, Common Weakness Enumeration
- NoSQL Databases Explained, MongoDB
- NoSQL Injection, RangeForce (Medium)
- A NoSQL Injection Primer (with Mongo), NullSweep