contrib.nodejsscan.nosql_injection.node_nosqli_js_injection

Author
99
Download Count*
License
Untrusted user input in MongoDB $where operator can result in NoSQL JavaScript Injection.
Run Locally
Run in CI
Defintion
rules:
- id: node_nosqli_js_injection
patterns:
- pattern-either:
- pattern: |
$OBJ.$FUNC({$where: <... $REQ.$FOO.$BAR ...>}, ...);
- pattern: |
$OBJ.$FUNC({$where: <... $REQ.$QUERY ...>}, ...);
- pattern: |
$NSQL = <... $REQ.$QUERY.$...>;
...
$OBJ.$FUNC({$where: <... $NSQL ...>}, ...);
- pattern: |
$NSQL = <... $REQ.$QUERY ...>;
...
$OBJ.$FUNC({$where: <... $NSQL ...>}, ...);
- pattern: |
$INP = $REQ.$FOO.$BAR;
...
$QRY = {$where: <... $INP ...>};
...
$OBJ.$FUNC(<... $QRY ...>, ...);
- pattern: |
$INP = $REQ.$FOO;
...
$QRY = {$where: <... $INP ...>};
...
$OBJ.$FUNC(<... $QRY ...>, ...);
- pattern: |
$QRY["$where"] = <... $REQ.$FOO ...>;
...
$OBJ.$FUNC(<... $QRY ...>, ...);
- pattern: |
$QRY["$where"] = <... $REQ.$FOO.$BAR ...>;
...
$OBJ.$FUNC(<... $QRY ...>, ...);
- pattern: |
$INP = $REQ.$FOO;
...
$QRY["$where"] = <... $INP ...>;
...
$OBJ.$FUNC(<... $QRY ...>, ...);
- pattern: |
$INP = $REQ.$FOO.$BAR;
...
$QRY["$where"] = <... $INP ...>;
...
$OBJ.$FUNC(<... $QRY ...>, ...);
message: Untrusted user input in MongoDB $where operator can result in NoSQL
JavaScript Injection.
languages:
- javascript
severity: ERROR
metadata:
owasp: A01:2017 - Injection
cwe: "CWE-943: Improper Neutralization of Special Elements in Data Query Logic"
category: security
technology:
- node.js
- express
license: Commons Clause License Condition v1.0[LGPL-2.1-only]
Examples
nosql_injection.js
var MongoClient = require('mongodb').MongoClient;
// mongo js injection https://lockmedown.com/securing-node-js-mongodb-security-injection-attacks/
timelineRouter.route("/api/timeline")
.get(async function (req, res) {
try {
var foo = req.foo.bar;
const startDate = "01/01/2000";
// ruleid:node_nosqli_js_injection
const endDate = req.query.end;
const query = { $where: "this.hidden == false" };
if (startDate && endDate) {
query["$where"] = "this.start >= new Date('" + startDate + "') && " +
"this.end <= new Date('" + endDate + "') &&" +
"this.hidden == false;";
}
const TimelineItem = await getTimelineItemModel();
const timelineItems = await TimelineItem.find(query);
console.log(colors.yellow(`# of Timeline Items retrieved: ${timelineItems.length}`));
return res.json({ timelineItems: timelineItems });
} catch (error) {
res.status(500).send("There was an error retrieving timeline items. Please try again later");
}
});
// https://nullsweep.com/a-nosql-injection-primer-with-mongo/
// ruleid:node_nosqli_js_injection
let username = req.query.username;
var query = { $where: `this.username == '${username}'` }
User.find(query, function (err, users) {
if (err) {
// Handle errors
} else {
res.render('userlookup', { title: 'User Lookup', users: users });
}
});
app.post('/foo', function (req, res) {
var query = {};
// ruleid:node_nosqli_js_injection
query['$where'] = `this.email == '${req.body.email}'`;
User.find(query, function (err, data) {
if (err) {
res.send(err);
} else if (data) {
res.send('User Login Successful');
} else {
res.send('Wrong Username Password Combination');
}
})
});
Short Link: https://sg.run/4xqL