Disable MongoDB server-side JavaScript
/etc/mongod.confsecurity: javascriptEnabled: falsesudo systemctl restart mongodWhy it matters
Section titled “Why it matters”MongoDB can evaluate JavaScript as part of a query. $where takes a JS
expression, $function and $accumulator run JS in aggregation pipelines, and
mapReduce is JS by definition.
The risk is injection. An application that interpolates user input into a
$where clause has handed the user a JavaScript expression evaluated by the
database:
// application code — the bugdb.users.find({ $where: `this.name == '${userInput}'` })Input of ' || true || ' makes the predicate always true and returns every
document, authorization checks on the query notwithstanding. Input containing a
while(true) loop consumes a server thread — a denial of service from a search
box.
Turning JS off removes the operator entirely. There is nothing to inject into.
Be honest about what this is not
Section titled “Be honest about what this is not”This is not remote code execution on the host, and a lot of writing implies it is.
MongoDB runs this JavaScript in an embedded SpiderMonkey interpreter with no
filesystem access, no network access, and no shell. An attacker who injects into
$where gets to evaluate an expression against documents and burn CPU. They do
not get a shell, they cannot write a file, and there is no equivalent of
Redis’s CONFIG SET dir or
MySQL’s UDF path.
So the realistic outcomes are query-logic bypass and denial of service —
both real, neither a host compromise. That’s why this is medium and not
critical, and why it sits below authorization, binding and roles on the list.
Fix those first.
You are probably not using it
Section titled “You are probably not using it”The reason this is an easy win: $where and mapReduce are slow, can’t use
indexes well, and have been discouraged by MongoDB for years. The aggregation
framework replaced mapReduce — MongoDB deprecated it in 4.4 — and query
operators cover nearly everything $where was used for.
Most applications written in the last several years use none of it, so this is usually a free removal. Check rather than assume, but expect to find nothing.
Related
Section titled “Related”- Grant least privilege roles — bounds what an injected query can reach.