UNPKG

@aikidosec/firewall

Version:

Zen by Aikido is an embedded Web Application Firewall that autonomously protects Node.js apps against common and critical attacks

73 lines (72 loc) 2.66 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.detectDbJsInjection = detectDbJsInjection; const isPlainObject_1 = require("../../helpers/isPlainObject"); const detectJsInjection_1 = require("./detectJsInjection"); // Operators accepting server-side JS code const serverSideJsFunctions = ["$where", "$accumulator", "$function"]; /** * Checks if the user input is part of queries that execute JS code on the server. * If the user input is part of the query and not safely encapsulated, it's considered an injection. * Because strings are always encapsulated in quotes in JS, every non-encapsulated user input is an injection. */ function detectDbJsInjection(userInput, filterPart) { for (const [key, value] of Object.entries(filterPart)) { if (!serverSideJsFunctions.includes(key)) { continue; } const jsCode = extractStringToCheck(key, value); if (typeof jsCode !== "string" || jsCode.length < 1) { continue; } return (0, detectJsInjection_1.detectJsInjection)(jsCode, userInput); } return false; } /** * Gets the code string to check for injections from a $where, $function or $accumulator object */ function extractStringToCheck(key, value) { if (typeof value === "string") { return value; } if (!(0, isPlainObject_1.isPlainObject)(value) || !value) { return undefined; } if (key !== "$function" && key !== "$accumulator") { return undefined; } if (typeof value.lang === "string" && value.lang !== "js") { return undefined; } // We can ignore args, because mongo is interpreting the body as JS code and passes the args to the function as string arguments. // You can not break out of a JS string with quotes inside a JS string. if (key === "$function") { if (typeof value.body !== "string") { return undefined; } return value.body; } else if (key === "$accumulator") { return extractCodeFromAccumulator(value); } } /** * Gets all js code strings from the $accumulator object and concatenates them */ function extractCodeFromAccumulator(accumulator) { let strToCheck = ""; if (typeof accumulator.init === "string") { strToCheck = accumulator.init; } if (typeof accumulator.accumulate === "string") { strToCheck += accumulator.accumulate; } if (typeof accumulator.merge === "string") { strToCheck += accumulator.merge; } if (typeof accumulator.finalize === "string") { strToCheck += accumulator.finalize; } return strToCheck; }