Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 21e6e69

Browse files
committed
JS: support mongodb v3 (minimally)
github/codeql-javascript-team#79
1 parent be09c17 commit 21e6e69

3 files changed

Lines changed: 47 additions & 2 deletions

File tree

javascript/ql/src/semmle/javascript/frameworks/NoSQL.qll

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,15 @@ private module MongoDB {
2323
*/
2424
private DataFlow::SourceNode getAMongoClient(DataFlow::TypeTracker t) {
2525
t.start() and
26-
result = mongodb().getAPropertyRead("MongoClient")
26+
(
27+
result = mongodb().getAPropertyRead("MongoClient")
28+
or
29+
exists(DataFlow::ParameterNode p |
30+
p = result and
31+
p = getAMongoDbCallback().getParameter(1) and
32+
not p.getName().toLowerCase() = "db" // mongodb v2 provides a `Db` here
33+
)
34+
)
2735
or
2836
exists(DataFlow::TypeTracker t2 | result = getAMongoClient(t2).track(t2, t))
2937
}
@@ -51,7 +59,15 @@ private module MongoDB {
5159
*/
5260
private DataFlow::SourceNode getAMongoDb(DataFlow::TypeTracker t) {
5361
t.start() and
54-
result = getAMongoDbCallback().getParameter(1)
62+
(
63+
exists(DataFlow::ParameterNode p |
64+
p = result and
65+
p = getAMongoDbCallback().getParameter(1) and
66+
not p.getName().toLowerCase() = "client" // mongodb v3 provides a `Mongoclient` here
67+
)
68+
or
69+
result = getAMongoClient().getAMethodCall("db")
70+
)
5571
or
5672
exists(DataFlow::TypeTracker t2 | result = getAMongoDb(t2).track(t2, t))
5773
}

javascript/ql/test/query-tests/Security/CWE-089/untyped/SqlInjection.expected

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ nodes
2020
| mongodb.js:49:19:49:33 | req.query.title |
2121
| mongodb.js:54:16:54:20 | query |
2222
| mongodb.js:54:16:54:20 | query |
23+
| mongodb.js:59:8:59:17 | query |
24+
| mongodb.js:59:16:59:17 | {} |
25+
| mongodb.js:60:16:60:30 | req.query.title |
26+
| mongodb.js:60:16:60:30 | req.query.title |
27+
| mongodb.js:65:12:65:16 | query |
28+
| mongodb.js:65:12:65:16 | query |
2329
| mongodb_bodySafe.js:23:11:23:20 | query |
2430
| mongodb_bodySafe.js:23:19:23:20 | {} |
2531
| mongodb_bodySafe.js:24:19:24:33 | req.query.title |
@@ -129,6 +135,17 @@ edges
129135
| mongodb.js:49:19:49:33 | req.query.title | mongodb.js:54:16:54:20 | query |
130136
| mongodb.js:49:19:49:33 | req.query.title | mongodb.js:54:16:54:20 | query |
131137
| mongodb.js:49:19:49:33 | req.query.title | mongodb.js:54:16:54:20 | query |
138+
| mongodb.js:59:8:59:17 | query | mongodb.js:65:12:65:16 | query |
139+
| mongodb.js:59:8:59:17 | query | mongodb.js:65:12:65:16 | query |
140+
| mongodb.js:59:16:59:17 | {} | mongodb.js:59:8:59:17 | query |
141+
| mongodb.js:60:16:60:30 | req.query.title | mongodb.js:59:8:59:17 | query |
142+
| mongodb.js:60:16:60:30 | req.query.title | mongodb.js:59:8:59:17 | query |
143+
| mongodb.js:60:16:60:30 | req.query.title | mongodb.js:59:16:59:17 | {} |
144+
| mongodb.js:60:16:60:30 | req.query.title | mongodb.js:59:16:59:17 | {} |
145+
| mongodb.js:60:16:60:30 | req.query.title | mongodb.js:65:12:65:16 | query |
146+
| mongodb.js:60:16:60:30 | req.query.title | mongodb.js:65:12:65:16 | query |
147+
| mongodb.js:60:16:60:30 | req.query.title | mongodb.js:65:12:65:16 | query |
148+
| mongodb.js:60:16:60:30 | req.query.title | mongodb.js:65:12:65:16 | query |
132149
| mongodb_bodySafe.js:23:11:23:20 | query | mongodb_bodySafe.js:29:16:29:20 | query |
133150
| mongodb_bodySafe.js:23:11:23:20 | query | mongodb_bodySafe.js:29:16:29:20 | query |
134151
| mongodb_bodySafe.js:23:19:23:20 | {} | mongodb_bodySafe.js:23:11:23:20 | query |
@@ -243,6 +260,7 @@ edges
243260
| mongodb.js:18:16:18:20 | query | mongodb.js:13:19:13:26 | req.body | mongodb.js:18:16:18:20 | query | This query depends on $@. | mongodb.js:13:19:13:26 | req.body | a user-provided value |
244261
| mongodb.js:32:18:32:45 | { title ... itle) } | mongodb.js:26:19:26:26 | req.body | mongodb.js:32:18:32:45 | { title ... itle) } | This query depends on $@. | mongodb.js:26:19:26:26 | req.body | a user-provided value |
245262
| mongodb.js:54:16:54:20 | query | mongodb.js:49:19:49:33 | req.query.title | mongodb.js:54:16:54:20 | query | This query depends on $@. | mongodb.js:49:19:49:33 | req.query.title | a user-provided value |
263+
| mongodb.js:65:12:65:16 | query | mongodb.js:60:16:60:30 | req.query.title | mongodb.js:65:12:65:16 | query | This query depends on $@. | mongodb.js:60:16:60:30 | req.query.title | a user-provided value |
246264
| mongodb_bodySafe.js:29:16:29:20 | query | mongodb_bodySafe.js:24:19:24:33 | req.query.title | mongodb_bodySafe.js:29:16:29:20 | query | This query depends on $@. | mongodb_bodySafe.js:24:19:24:33 | req.query.title | a user-provided value |
247265
| mongoose.js:27:20:27:24 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:27:20:27:24 | query | This query depends on $@. | mongoose.js:21:19:21:26 | req.body | a user-provided value |
248266
| mongoose.js:30:25:30:29 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:30:25:30:29 | query | This query depends on $@. | mongoose.js:21:19:21:26 | req.body | a user-provided value |

javascript/ql/test/query-tests/Security/CWE-089/untyped/mongodb.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,14 @@ app.post('/documents/find', (req, res) => {
5454
doc.find(query);
5555
});
5656
});
57+
58+
app.post('/documents/find', (req, res) => {
59+
const query = {};
60+
query.title = req.query.title;
61+
MongoClient.connect('mongodb://localhost:27017/test', (err, client) => {
62+
let doc = client.db("MASTER").collection('doc');
63+
64+
// NOT OK: query is tainted by user-provided object value
65+
doc.find(query);
66+
});
67+
});

0 commit comments

Comments
 (0)