
NoSQL Injection (NoSQLi): How They Work and How to Defend Yourself
Celia CatalánShare
NoSQL Injections (NoSQLi)
NoSQL databases are data storage systems designed to handle large volumes of unstructured (or semi-structured) information, unlike the information managed by traditional relational databases (SQL or Structured Query Language).
Most Used Types of NoSQL Databases
According to the different utilities of the information, databases are classified into:
- Document Databases: The information is stored in the form of JSON documents - JavaScript Object Notation, a lightweight data serialization and exchange format - or BSON - Binary JSON, a binary-encoded JSON format instead of text format, like the former). In this category, CouchDB (JSON) or MongoDB (BSON) would stand out.
- Key-Value Databases: Data is stored as key-value pairs. In this sense, they refer to Redis or DynamoDB.
- Graph databases: They are characterized by the fact that the information is used to prioritize the modeling of relationships between the data. The most commonly used for this type are Neo4j or ArangoDB.
- Columnar database formats: Information storage is prioritized in columnar format. Examples of this type would be Apache Cassandra or HBase.
What is NoSQL Injection (NoSQLi)?
A NoSQL injection occurs when an attacker manipulates NoSQL queries, taking advantage of incorrect validation of user inputs or parameters, thus allowing the execution of unwanted statements, different from those specifically created for the exploited functionality, just as with SQL injections. The main difference with these typical structures of relational models lies in the fact that here we will not work with table structures organized in rows and columns, as seen in the previous section, nor with the SQL language, but with specific languages of each NoSQL management system (JSON, BSON, CQL, etc.). Generally, different formats will be interacted with, usually through the use of dynamic queries, which are less rigid, allowing manipulation of the information to exploit the vulnerability present in the application.
Examples of NoSQLi attacks in different NoSQL DBMS
Next, typical exploitation scenarios will be analyzed depending on the different configurations in the Database Management Systems or NoSQL database managers used.
1. MongoDB
'MongoDB uses JSON to perform queries. When storing the JSON document, it will be converted to its corresponding BSON (binary) format. A typical query to verify credentials could be:'
Find users in the database where the username is "admin" and the password is "Passw0rd!".
Basic attack
If the input is not sanitized, an attacker could send:
{ "username": { "$ne": null }, "password": { "$ne": null } }
This generates the query:
Find users in the database where the username is not null and the password is not null.
Thus, the result will bypass credential validation and the attacker will gain access to the system, similar to how one could evade the authentication mechanisms of a form with traditional SQLi using the classic injection ' OR 1=1 -- or similar.
Note that if db.users.findOne were used, it would retrieve the first user from the database, which is usually the administrator.
2. Redis
Redis is a key-value database that allows commands like GET and SET. A typical attack could involve manipulating keys to obtain information different from what is intended to be retrieved.
Suppose that an application queries keys with:
GET user:admin
Basic attack
An attacker could inject:
GET user:*
'By using the wildcard '*' all keys that match the pattern will be returned and, therefore, list all users of the application.'
3. Apache Cassandra
Cassandra uses CQL (Cassandra Query Language), similar to SQL, but adapted to its column model. This is why NoSQLi attacks related to this query system may resemble traditional SQLi more than the others analyzed in this post.
A typical query to search for users could be:
SELECT * FROM users WHERE username = 'admin' AND password = 'Passw0rd!';
Basic attack
In this way, an attacker could inject:
' OR '1'='1
Which would generate:
SELECT * FROM users WHERE username = '**' OR '1'='1**' AND password = ''
... accessing all users of the system in this way.
4. Neo4j
'Neo4j uses Cypher as its query language. A typical query to search for nodes could be:'
MATCH (u:User {username: 'admin', password: 'Passw0rd!'}) RETURN u;
Basic attack
An attacker could inject:
MATCH (u) RETURN u //
... and, consequently, all the nodes of the database could be returned.
Obfuscation and Evasion Techniques
Detection systems like WAF (Web Application Firewall) often block common injection patterns. However, attackers can use advanced techniques to evade them, as seen in SQLi attacks and other types of injections. Similarly to SQL databases, but applied to this type of database, the following techniques can be employed:
1. Coding
Encoding special characters can help prevent WAFs from detecting suspicious patterns.
Hexadecimal encoding
Convert characters to their hexadecimal representation:
{ "$ne": null } → { "$ne": null }
Base64 Encoding
Encode the complete payload in base64 (and decode later on the client):
{ "$ne": null } → ey AiJG5lIjogbnVsbCB9Cg==
2. Comments
This technique consists of inserting comments to bypass detection rules. For example, in Neo4j, the code seen before can be injected to retrieve all users, but by first inserting a comment:
MATCH /* loquesea */ (u) RETURN u
3. Concatenation
Using concatenation (+), just as with evasion in SQLi, strings can be fragmented to separate the payload and thus avoid direct detections. For example, in the case of MongoDB:
{ "username": { "$n" + "e": null } }
4. Use of control characters or Unicode spaces (invisible characters)
Sometimes the use of certain characters that do not really modify the query can be employed in injections to break the detection patterns of WAFs. For example, in the case seen for Redis, incorporating before the use of the wildcard (*) the Unicode character equivalent to "zero-width space" (Unicode character 200B).
GET user:\\u200B*
Prevention measures
1. Validation and cleansing
• Use of strict validations on the server side.
• Rejection of special characters or unexpected structures for the implementation of specific functionality. It is better to limit by the desired values that are expected to be received rather than by more "open" values that could be exploited by an attacker or escape functions that may be incomplete. In this latter case, and if necessary, use existing libraries and functionalities. One should always seek to "not reinvent the wheel" in this regard.
2. Use of secure libraries
Establish the use of safe operators. For example, use $eq in MongoDB:
Find users in the database where the username is equal to "admin" and the password is equal to "Passw0rd!".
This way, the construction of overly "open" dynamic queries would be avoided. This should also be taken into account for those cases where regular expressions are used.
3. Principle of Least Privilege or limitation of user permissions.
It is always recommended to limit employee user permissions to access only the information they need to access and no other, being restricted to the scope of the database in question.
4. Use of WAF (Web Application Firewall)
"The WAF should be used to block specific patterns of NoSQLi, but never forgetting to follow good secure development practices to prevent the evasion of such patterns from leading to a successful attack against the application."
Conclusion
When considering NoSQL databases for the competitive advantage they offer in terms of flexibility, scalability, and handling large volumes of information, it also opens the door to new attack surfaces, with methods similar to traditional SQLi, such as NoSQLi. Unlike these traditional attacks, here the unstructured nature of the information is exploited, generally through the manipulation of associated JSON/BSON files.
It is essential that both developers and system administrators, as well as database administrators, adopt a multi-layered security approach, which includes proper validation and sanitization of input parameters (adapted to the new management systems used), the use of secure libraries, and an appropriate (and limited) configuration regarding the system and the permissions employed.
Furthermore, the compression of the evasion techniques used by attackers, and the conduct of periodic security tests can help improve defenses against this type of threat.
Finally, although NoSQLi shares similarities with SQLi, the differences between the NoSQL languages and structures used will require different and unique approaches to secure these systems against various attacks.
Roberto Trigo, Cybersecurity Consultant at Zerolynx.