noSQL
NoSQL Injection
This is a vulnerability similar to sql injection but instead of manipulating the sql query which the application performs, we interfare with noSQL query that the application makes to its backend noSQL database. This may cause an attacker to.
Bypass authentication mechanism
Perform code execution on the server
Extract or even modify data
Cause a denial of service attack
Authentication Bypass example
The above request performs following query via noSQL query on backend mongodb database
Types of nosql injection
Syntax Injection
This is a technique where an attacker breaks out of a noSQL query in order to inject his/her own query. For example in the following nodejs code the item name is taken via GET request https://example.com/search?item=toothpaste and passing it to mongodb's find method db.Product.find({name:"toothpaste"})
To test for vulnerability here we try to break the query syntax using fuzz strings relevant to noSQL query like ' " } ) { ( ; ;
etc to trigger a database error or some detectable difference in the application's response.
Breaking Syntax
Via url encode while passing request via url
Breaking syntax in case of JSON
Testing each character to identify exactly which character is breaking the string
The following '
character breaks the query and causes error or difference
Again use escape sequence to escape this character and observe the response. IF it is equal as original response we have identified the vulnerability.
After identiying the vulnerability
After identifying the vulnerability we need to determine whether boolean condition is processed or not. Here we test using True and False. This one is false ' && 0 && 'x
and this one is true ' && 1 && 'x
.
Test for false condition and notice the difference
Test for true condition and notice the difference.
If the application behaves differently, this suggests that the false condition impacts the query logic, but the true condition doesn't. This indicates that injecting this style of syntax impacts a server-side query.
We can also add null character after a payload which will comment the rest of the query
'\u0000
or"\u0000
Data Extraction via syntax injection
In many nosql databases some query operations or functions can run limited javascript code such as mongodb's $where
operator and mapReduce()
function. Using javascript we may be able to extract data from the database. For examppe there exists a functionality where users can lookup users and their respective roles via
This results in following noSQL query being executed in the users collection.
We can inject javascript function to find each character of this user's password. First we find the length of the password.
Here, as below username = alex AND first character of password is a if becomes true and since 'a' is not equal to b then TRUE OR FLASE is true then some change might happen in the application response else username is Alex and if password's first character is not equal to a then it becomes false so TRUE AND FALSE is FALSE and FALSE and FALSE becomes false and application might behave differently in this order we can guess each character.
We can also use javascript's match() function to extract information, for eg: for finding if the password contains any digits
How do we identify valid fields?
Since mongodb does not have a fixed schema like sql we can identify valid field as follows https://insecure-website.com/user/lookup?username=admin'+%26%26+this.password!%3d'
. Here we are testing the password field is not empty.
SImilarly to identify other fields
NoSQL operator Injections
Useful Operators
Authentication Bypass via operator injection
Test for $ne operators
{"username": "Alex"}
becomes{username: {"$ne":"Invalid"}}
In case of url query /?username=alex becomes
/?username[$ne]=Invalid
Maybe try converting the method from get to post then change content type to json?
Test each input field for operator injection
{"username":"Alex", "password":{"$ne":"Test"}}
again on password field{"username": {"$ne": "Test@123"}, "password": {"$ne": "12345"} }
Using known or guessed username we can target an account via
{"username":{"$in":["admin","administrator","superadmin"]},"password":{"$ne":"12345"}}
We can use regex operator like below if the password of Administrator starts with T it lets us login.
Data extraction via operator injection
If the original query doesnot use any javascript operators we may be able to inject $where
operator ourself. Considering a vulnerable application that accepts a username and password via POST request.
To test whether you can inject operators, you could try adding the $where operator as an additional parameter, then send one request where the condition evaluates to false, and another that evaluates to true. For example:
If there is a difference in the application's response this may indicate that the javascript expression is evaluated. Now we can extract the keys using keys() method as follows.
Time based inections
Sometimes triggering a database error doesn't cause a difference in the application's response. In this situation, you may still be able to detect and exploit the vulnerability by using JavaScript injection to trigger a conditional time delay.
To conduct timing-based NoSQL injection:
Load the page several times to determine a baseline loading time.
Insert a timing based payload into the input. A timing based payload causes an intentional delay in the response when executed. For example, {"$where": "sleep(5000)"}
causes an intentional delay of 5000 ms on successful injection.
Identify whether the response loads more slowly. This indicates a successful injection.
The following timing based payloads will trigger a time delay if the password beings with the letter a: admin'+function(x){var waitTill = new Date(new Date().getTime() + 5000);while((x.password[0]==="a") && waitTill > new Date()){};}(this)+'
admin'+function(x){if(x.password[0]==="a"){sleep(5000)};}(this)+'
Last updated