NoSQL Injection: How malicious input can compromise your application

Unlike traditional SQL databases, which use a structured language (SQL) to perform queries, NoSQL databases can handle non-relational data structures and allow for more flexible and often less stringent queries. For example, in NoSQL databases, queries can vary significantly in their format, from JSON documents in MongoDB, to graph-based queries in Neo4j. This flexibility, combined with the lack of strict typing and validation in some implementations, can lead to significant security flaws.
Developers and security teams often underestimate the security risks associated with NoSQL databases due to a lack of specialized knowledge and the mistaken assumption that database-related injections are a problem unique to SQL. However, in the OWASP injection category, this vulnerability occupies the third position. 94% of the applications evaluated had some type of injection, with a maximum incidence rate of 19% and a mean incidence rate of 3%, accumulating a total of 274,000 occurrences.
NoSQL injections, which affect NoSQL databases, such as MongoDB, CouchDB, or Cassandra, occur when an attacker manipulates user input to alter queries being made to a NoSQL database. NoSQL injection attacks can occur in different parts of an application compared to traditional SQL injections. While SQL injections are typically executed within the database engine, NoSQL variants can be executed at the application layer or at the database layer, depending on the NoSQL API used and the data model. Typically, these attacks are carried out where the malicious string is parsed, evaluated, or concatenated into a NoSQL API call.
Injection relies on manipulating the query structure to alter syntax and gain unauthorized access or modify data. Although the methodology is similar to that of SQL injections, differences in NoSQL query languages and structures require specific approaches.
A classic example is injecting a query operator that changes the logic of the original query. Let us imagine a web application that uses MongoDB and authenticates users by checking whether the username and password match a record in the database:
db.users.find({ "username": userInput.username, "password": userInput.password }); |
If userInput.username
is manipulated to become {"$gt": ""}
and userInput.password
is an arbitrary value, the query might return all records where the username is larger than an empty string, thus bypassing authentication. The $gt operator
in MongoDB stands for "greater than" and, in this case, compares the username
field to an empty string (all documents where the username
is greater than an empty string). Because most records meet this condition, the second condition (password
) is irrelevant because the first filter has already caused many records to pass the first filter, making it easier to bypass authentication.
Let us look at another example based on operator injection. NoSQL databases typically offer a variety of operators for filtering, comparing, and advanced searches, such as $or, $and, $regex
, and $ne
in MongoDB. An attacker can leverage these operators to modify the query and gain access to data or alter its contents. In MongoDB, an attacker could use the $or
operator to modify the authentication query and ensure that a condition is always met, allowing access to the database without valid credentials:
db.users.find({ "username": userInput.username, "password": { "$or": [{ "$ne": "dummy" }, { "$exists": true }] } }); |
In this case, the $or
operator ensures that the query is always true if either of the two conditions is met: that the password
is not equal to a dummy, or that the password
field simply exists. In this way, even if the password
provided is incorrect, the query still returns a valid result, which allows the authentication mechanism to be circumvented.
Risk and impact factors
NoSQL injections pose a significant security risk to web applications that use NoSQL databases. These risk factors include:
Exploitation of unvalidated inputs: NoSQL injections often arise when web applications do not properly validate user inputs. This allows an attacker to manipulate database queries by injecting malicious data, which can lead to the exposure or alteration of sensitive data. Dynamic queries, which are common in NoSQL databases, can be particularly vulnerable if they are constructed using user input data without proper sanitation or parameterization.
Lack of access controls: on some systems, a lack of proper access controls can allow attackers to make queries or modifications to the database that would normally be restricted. This is compounded if the database credentials are overprivileged.
Improper use of query operators: improper use of query operators (such as $or, $regex, etc.) in NoSQL databases can facilitate injection attacks. Through the exploitation of these operators to manipulate query logic and gain unauthorized access to data or alter information.
Impacts refer to the consequences or adverse effects that emerge when a vulnerability is exploited. These impacts illustrate the potential damage an organization may face if an attack is successful:
Data access and modification: it would allow critical data to be read, modified or deleted, which can lead to decisions based on altered information, corruption of records, manipulation of financial transactions or loss of historical data. This can cause irreparable damage to the organization's day-to-day operations, strategic decisions, and reputation, and could be used to hide fraudulent activity or further damaging attacks. Exposure of sensitive data can result in legal and financial consequences, such as fines for non-compliance with regulations (e.g., GDPR).
Code execution on the server: it could lead to the installation of malware, ransomware, or other malicious programs, compromising the server. This can disrupt services, steal information, destroy data, and spread malicious code. It could also allow for privilege escalation or lateral movement within IT infrastructure, increasing the risk of a broader attack on multiple critical systems.
Denial of Service (DoS) attacks: an attacker could manipulate queries to overload the database server, slowing down or blocking business-critical applications.
NoSQL vulnerability discovery and assessment
Below are the NoSQL vulnerability discovery methods that can be used by testers or auditors to discover and fix these vulnerabilities:
Injection of true conditions: in this test, the use of a condition that is always true, such as 1 == 1, is leveraged to alter the validation logic and evade authentication constraints.
Manipulation of comparison conditions: this technique attempts to modify queries by using operators such as $ne (not equal) to make the condition always true. If the system does not validate correctly, the authentication check can be bypassed. One way to test this vulnerability is to use something like: {$ne:1}.
Logical operator injection: in this case, it is verified whether it is possible to manipulate the query using logical operators such as $or. Injecting multiple conditions to ensure that at least one is true can bypass validation checks. An attack might use: ', $or: [ {}, { 'a':'a' } ].
$comment injection: this approach explores whether a comment can be injected into the query to gain additional information or identify weaknesses in the application. Although comments do not change the logic of the query, they can help uncover vulnerabilities. An example to test this is: $comment: 'successful MongoDB injection'.
Infinite-loop injection or resource consumption: this involves overloading the system by injecting code that generates infinite loops or consumes resources. If your application does not properly handle these inputs, it could be vulnerable to a denial-of-service attack. To test this type of attack, one could try with: '; sleep(5000);'.
Regular Expression Injection: this technique injects regular expressions into key fields such as passwords. If the system does not correctly validate these inputs, an expression such as /.*/ could cause any value to be accepted. It could be tested by: ' && this.password.match(/.*/)//+%00.
Injection of empty comparisons: this seeks to circumvent authentication by using comparison operators such as $gt, which select records based on comparisons with empty or undefined values. If the system does not validate these comparisons correctly, it could return undesired results. This could be tested by: {"username": {"$gt": ""}}.
Safeguards and best practices
To protect web applications against NoSQL injections, it is crucial to adopt a security strategy that combines multiple layers of defense. NoSQL databases, because of their flexible and non-relational nature, present unique challenges in terms of security, and the techniques that work to protect SQL databases are not always applicable or sufficient. The following describes best practices and protective measures for mitigating NoSQL injection vulnerabilities.
Strict validation of user inputs: input validation is the first line of defense against NoSQL injections. It is critical to implement robust controls to ensure that user inputs are correct and secure:
Sanitizing inputs: all user inputs should be sanitized to remove special characters or sequences that could be used to modify queries. This includes both direct (forms, URL parameters) and indirect (HTTP headers, cookies) inputs.
Data type validation: you need to make sure that the inputs are of the expected type. For example, if a number is expected, the application must validate that the input is numeric and reject any value that is not. In the case of JSON, the expected data types should be checked to prevent injections of malicious JSON objects.
Whitelists and blacklists: implement whitelists to limit entries to only those values or characters that are acceptable. Blacklists, while useful as a secondary measure, should not be the only defense, as it is difficult to foresee all possible malicious payloads.
Use of parameterized and prepared queries: the use of parameterized or prepared queries is one of the most effective measures against NoSQL injections. These techniques allow you to construct queries in which the user's input data is handled securely, separating it from the query logic:
Parameterized queries: these queries use parameters instead of concatenating user inputs directly into queries. Parameters allow the database to interpret user data as simple input values, not as part of query logic. In MongoDB, for example, methods such as findOne or updateOne can be used with predefined filter and update objects to prevent injections.
Prepared queries: some NoSQL databases, such as Cassandra, support prepared queries. These queries are precompiled on the database server and accept only parameter values as input, minimizing the risk of injection.
Implementing robust access controls: having well-designed access controls is essential to mitigate the risk of NoSQL injections and other types of attacks:
Principle of least privilege: ensure that database accounts and roles have as few privileges as possible. For example, an application account that only needs to read data must not have write or delete permissions.
Granular authentication and authorization: use granular authentication and authorization schemes to restrict access to specific resources based on the user's role. In addition, databases allow the use of role-based authentication (RBAC), which can be used to define fine-grained access policies.
Query rate and quota limits: implement mechanisms to limit query rates and set usage quotas to prevent brute force attacks and abuses.
Continuous monitoring and detection of suspicious activity by logging queries and database activities to detect attack patterns or implementing intrusion detection systems (IDS) and behavioral analysis tools that monitor anomalous query patterns. For example, an unusually high number of read or modify queries can be an indicator of an attack in progress.
Regular updating and security patches, keeping all libraries and databases up to date. NoSQL databases and their connection drivers receive updates and security patches that address discovered vulnerabilities. In addition, it is necessary to stay on top of the security alerts and vulnerabilities published for the NoSQL database used and for all related dependencies, so that you can apply security recommendations as soon as possible.
Conclusion
NoSQL injections pose a significant security threat to web applications that use NoSQL databases, primarily due to the flexibility and dynamic nature of the queries. These vulnerabilities can put the basic pillars of information security at risk, so in the face of these dangers, it is vital to take a proactive approach to reduce these threats.
In order to effectively protect applications, it is necessary to adopt a defense strategy as today's cybersecurity threat landscape is constantly changing. Therefore, developers need to stay up-to-date in order to respond to these threats effectively. Continuously reviewing the effectiveness of these measures involves conducting regular security audits, penetration tests, and risk analysis. This ensures that systems and applications are better protected.