2023-03-07 17:16:47 +01:00

75 lines
2.6 KiB
Plaintext

== How to fix it in MongoDB
=== Code examples
The following code is vulnerable to arbitrary code execution because it builds
a JavaScript code snippet from untrusted data. This piece of code is then used
as an operand for a dangerous *evaluation* MongoDB operator.
When performing a database query that way, the MongoDB server will interpret
the JavaScript code as part of the data retrieval process. This might lead to
arbitrary code execution on the database server.
==== Noncompliant code example
[source,javascript,diff-id=1,diff-type=noncompliant]
----
const client = new MongoClient(mongoURI);
async function run() {
const database = client.db('example');
const products = database.collection('product');
const query = { $where: `isString(this.${req.query.prop})`};
const product = await products.findOne(query); // Noncompliant
}
run().catch(console.dir);
----
==== Compliant solution
[source,javascript,diff-id=1,diff-type=compliant]
----
const client = new MongoClient(mongoURI);
async function run() {
const allowed = ["name", "price", "stock"]
let propId = req.query.propId
const database = client.db('example');
const products = database.collection('product');
const query = { $where: `isString(this.${allowed[propId]})`};
const product = await products.findOne(query); // Noncompliant
}
run().catch(console.dir);
----
=== How does this work?
MongoDB provides JavaScript code-aware search operators to allow developers to
perform advanced queries. In most cases, the same result can be achieved by
combining classical, safer, operators, or by performing additional data
filtering on the application side.
Note that MongoDB servers implement a sandboxed JavaScript engine to run the
operator-related code. Without other vulnerabilities in the database engine,
the execution of arbitrary code is thus not possible through the exploitation
of evaluation operators. However, a successful injection could still lead to
the compromise of the MongoDB server hosted data. Moreover, the discovery by
an attacker of a way to escape the sandbox should also be considered.
==== Safer operators
Wherever possible, safe operators that do not evaluate JavaScript
expressions should be preferred over dangerous ones. Dangerous operators
include:
* `$where`
* `$accumulator`
* `$function`
If the application requires a complex logic to properly filter a query's
results, it might be considered to implement it on the application side rather
than in the database itself. That way, only simple operators can be used in the
database query.
include::../../common/fix/allowlist.adoc[]
The example compliant code uses such a binding approach.