Database Layer

Dated Jun 16, 2024; last modified on Sun, 16 Jun 2024

Currently using MongoDB’s free tier, which has shared RAM, and up to 5GB of storage . So far, the overall DB usage has been less than 5MB.

Query Injection

Current State of Affairs

Currently have this protection implemented back in 2018:

/**
 * @description Prevent a NoSQL Injection in the search parameters. This is
 * achieved by deleting all query values that begin with `$`.
 */
export function sanitizeQuery(query: any) {
  const keys = Object.keys(query);
  for (let i = 0; i < keys.length; i++) {
    if (/^\$/.test(query[keys[i]])) { delete query[keys[i]]; }
  }
  return query;
}

We can do better than roll out our own NoSQL injection protection; this is a common enough problem that libraries should have protections for.

MongoDB Injection Attacks

For MongoDB in a JS environment, one can set security.javascriptEnabled to false in the mongod configuration to disallow JS execution on the server. Otherwise, an attacker can run arbitrary JS in these MongoDB operations: $where, mapReduce, $accumulator, and $function.

CodeQL did flag code like User.findOne({email: payload.email}) as js/sql-injection violation, and suggested User.findOne({email: { $eq: payload.email }}) instead. The use of eq ensures that the input is interpreted as a literal value and not a query object. Alternatively, checking that typeof payload.email === "string" also provides protection against NoSQL injection.

Reading , I don’t think I’d have gotten to without the hint from . Does Mongoose’s Model.findOne internally use $where and that’s why flags it?

has concrete examples of NoSQL injection attacks:

db.myCollection.find({
  active: true,
  $where: function() { return obj.credits - obj.debits < $userInput; }
});

// A string containing any of these unsanitized characters would cause a
// database error.
const maliciousInput = `' " \ ; { }`;

// If inserted into `$userInput`, the MongoDB instance would execute at
// 100% CPU usage for 10 seconds.
const injection = `0;var date=new Date(); do{curDate = new Date();}while(curDate-date<10000)`;

also brings up an alternate injection attack in a language like PHP, where PHP would try to substitute $where with the value of the variable $where. However, this doesn’t apply to the current project.

A sample NoSQL injection is navigating to /trpc/fetchPublicCard?batch=1&input=%7B%220%22%3A%7B%22cardID%22%3A%7B%22%24ne%22%3A%22000000000000000000000000%22%7D%7D%7D. The user should not be able to execute a query like {cardID: {$ne: "000000000000000000000000" } and fetch a card. The tRPC endpoint should be able to strip out the non-literal card ID.

What about vanilla Express endpoints? CodeQL highlighted the injection attack surfaces for endpoints like /login, /account, /reset-password, and /send-validation-email and we fixed them. Seems like CodeQL’s queries are good at finding vulnerabilities in Express, but not in tRPC.

NoSQL Injection Prevention Libraries

is similar to in that it strips out keys that start with $, but goes one step further by stripping out such keys recursively.

sanitizes keys that begin with either $ or .. It can also be used as middleware allowing it to sanitize fields such as req.body, req.params, req.headers, and req.query. It can also be used in a non-middleware context, allowing it to be a drop-in replacement for .

db.inventory.find({"price.usd": { $gt: 40 }}) would match the document

{
   "item" : "sweatshirt",
   "price": {
      "usd": 45.99
   },
   "quantity": 20
}

. Is that what means by “. could change the context of a database operation”?

Doing app.use(mongoSanitize()) as advised by doesn’t prevent injection attacks via tRPC.

References

  1. Pricing | MongoDB. www.mongodb.com . Accessed Jun 16, 2024.
  2. Sanitize card content and queries. Store card HTML server-side. · dchege711/study_buddy@186da7c. github.com . github.com . Nov 16, 2018. Accessed Jun 16, 2024.
  3. FAQ: MongoDB Fundamentals - MongoDB Manual v7.0. www.mongodb.com . Accessed Jun 16, 2024.
  4. [DB] Fix js/sql-injection violations · dchege711/study_buddy@0d57acc. github.com . Jun 8, 2024. Accessed Jun 16, 2024.
  5. Database query built from user-controlled sources — CodeQL query help documentation. codeql.github.com . Accessed Jun 16, 2024.
  6. WSTG - Latest | OWASP Foundation. owasp.org . Accessed Jun 16, 2024.
  7. mongo-sanitize - npm. www.npmjs.com . Mar 2, 2020. Accessed Jun 16, 2024.
  8. express-mongo-sanitize - npm. www.npmjs.com . Jan 14, 2022. Accessed Jun 16, 2024.
  9. Field Names with Periods - MongoDB Manual v7.0. www.mongodb.com . Accessed Jun 16, 2024.
  10. [DB] Fix js/sql-injection violations · dchege711/study_buddy@0f5b088. github.com . Jun 9, 2024. Accessed Jun 24, 2024.