JS: model marsdb and minimongo

This commit is contained in:
Esben Sparre Andreasen
2020-05-12 19:24:17 +02:00
parent f5e491caf0
commit 20cf04442c
8 changed files with 214 additions and 0 deletions

View File

@@ -6,6 +6,8 @@
- [fstream](https://www.npmjs.com/package/fstream)
- [jGrowl](https://github.com/stanlemon/jGrowl)
- [jQuery](https://jquery.com/)
- [marsdb](https://www.npmjs.com/package/marsdb)
- [minimongo](https://www.npmjs.com/package/minimongo/)
## New queries

View File

@@ -713,3 +713,101 @@ private module Mongoose {
}
}
}
/**
* Provides classes modeling the Minimongo library.
*/
private module Minimongo {
/**
* Gets an expression that may refer to a Minimongo database.
*/
private DataFlow::SourceNode getADb(DataFlow::TypeTracker t) {
t.start() and
// new (require('minimongo')[DBKINDNAME])()
result = DataFlow::moduleImport("minimongo").getAPropertyRead().getAnInvocation()
or
exists(DataFlow::TypeTracker t2 | result = getADb(t2).track(t2, t))
}
/** Gets a data flow node referring to a Minimongo collection. */
private DataFlow::SourceNode getACollection(DataFlow::TypeTracker t) {
t.start() and
// db[COLLECTIONNAME]
result = getADb(DataFlow::TypeTracker::end()).getAPropertyRead()
or
exists(DataFlow::TypeTracker t2 | result = getACollection(t2).track(t2, t))
}
module CollectionMethodSignatures {
predicate interpretsArgumentAsQuery(string m, int queryArgIdx) {
// implements most of the MongoDB interface
MongoDB::CollectionMethodSignatures::interpretsArgumentAsQuery(m, queryArgIdx)
}
}
/** A call to a Minimongo query method. */
private class QueryCall extends DatabaseAccess, DataFlow::MethodCallNode {
int queryArgIdx;
QueryCall() {
exists(string m | this = getACollection(DataFlow::TypeTracker::end()).getAMethodCall(m) |
CollectionMethodSignatures::interpretsArgumentAsQuery(m, queryArgIdx)
)
}
override DataFlow::Node getAQueryArgument() { result = getArgument(queryArgIdx) }
}
/**
* An expression that is interpreted as a Minimongo query.
*/
class Query extends NoSQL::Query {
Query() { this = any(QueryCall qc).getAQueryArgument().asExpr() }
}
}
/**
* Provides classes modeling the MarsDB library.
*/
private module MarsDB {
/**
* Gets an expression that may refer to a MarsDB database.
*/
private DataFlow::SourceNode getADb(DataFlow::TypeTracker t) {
t.start() and
// Collection = require('marsdb')
result = DataFlow::moduleImport("marsdb")
or
exists(DataFlow::TypeTracker t2 | result = getADb(t2).track(t2, t))
}
/** Gets a data flow node referring to a MarsDB collection. */
private DataFlow::SourceNode getACollection(DataFlow::TypeTracker t) {
t.start() and
// new Collection(...)
result = getADb(DataFlow::TypeTracker::end()).getAPropertyRead("Collection").getAnInvocation()
or
exists(DataFlow::TypeTracker t2 | result = getACollection(t2).track(t2, t))
}
/** A call to a MarsDB query method. */
private class QueryCall extends DatabaseAccess, DataFlow::MethodCallNode {
int queryArgIdx;
QueryCall() {
exists(string m | this = getACollection(DataFlow::TypeTracker::end()).getAMethodCall(m) |
// implements parts of the Minimongo interface
Minimongo::CollectionMethodSignatures::interpretsArgumentAsQuery(m, queryArgIdx)
)
}
override DataFlow::Node getAQueryArgument() { result = getArgument(queryArgIdx) }
}
/**
* An expression that is interpreted as a MarsDB query.
*/
class Query extends NoSQL::Query {
Query() { this = any(QueryCall qc).getAQueryArgument().asExpr() }
}
}

View File

@@ -1,3 +1,6 @@
| marsdb-flow-to.js:14:3:14:22 | db.myDoc.find(query) |
| marsdb.js:16:3:16:17 | doc.find(query) |
| minimongo.js:18:3:18:17 | doc.find(query) |
| mongodb.js:18:7:18:21 | doc.find(query) |
| mongodb.js:21:7:21:48 | doc.fin ... itle }) |
| mongodb.js:24:7:24:53 | doc.fin ... r(1) }) |

View File

@@ -1,4 +1,25 @@
nodes
| marsdb-flow-to.js:10:9:10:18 | query |
| marsdb-flow-to.js:10:17:10:18 | {} |
| marsdb-flow-to.js:11:17:11:24 | req.body |
| marsdb-flow-to.js:11:17:11:24 | req.body |
| marsdb-flow-to.js:11:17:11:30 | req.body.title |
| marsdb-flow-to.js:14:17:14:21 | query |
| marsdb-flow-to.js:14:17:14:21 | query |
| marsdb.js:12:9:12:18 | query |
| marsdb.js:12:17:12:18 | {} |
| marsdb.js:13:17:13:24 | req.body |
| marsdb.js:13:17:13:24 | req.body |
| marsdb.js:13:17:13:30 | req.body.title |
| marsdb.js:16:12:16:16 | query |
| marsdb.js:16:12:16:16 | query |
| minimongo.js:14:9:14:18 | query |
| minimongo.js:14:17:14:18 | {} |
| minimongo.js:15:17:15:24 | req.body |
| minimongo.js:15:17:15:24 | req.body |
| minimongo.js:15:17:15:30 | req.body.title |
| minimongo.js:18:12:18:16 | query |
| minimongo.js:18:12:18:16 | query |
| mongodb.js:12:11:12:20 | query |
| mongodb.js:12:19:12:20 | {} |
| mongodb.js:13:19:13:26 | req.body |
@@ -150,6 +171,33 @@ nodes
| tst.js:10:46:10:58 | req.params.id |
| tst.js:10:46:10:58 | req.params.id |
edges
| marsdb-flow-to.js:10:9:10:18 | query | marsdb-flow-to.js:14:17:14:21 | query |
| marsdb-flow-to.js:10:9:10:18 | query | marsdb-flow-to.js:14:17:14:21 | query |
| marsdb-flow-to.js:10:17:10:18 | {} | marsdb-flow-to.js:10:9:10:18 | query |
| marsdb-flow-to.js:11:17:11:24 | req.body | marsdb-flow-to.js:11:17:11:30 | req.body.title |
| marsdb-flow-to.js:11:17:11:24 | req.body | marsdb-flow-to.js:11:17:11:30 | req.body.title |
| marsdb-flow-to.js:11:17:11:30 | req.body.title | marsdb-flow-to.js:10:9:10:18 | query |
| marsdb-flow-to.js:11:17:11:30 | req.body.title | marsdb-flow-to.js:10:17:10:18 | {} |
| marsdb-flow-to.js:11:17:11:30 | req.body.title | marsdb-flow-to.js:14:17:14:21 | query |
| marsdb-flow-to.js:11:17:11:30 | req.body.title | marsdb-flow-to.js:14:17:14:21 | query |
| marsdb.js:12:9:12:18 | query | marsdb.js:16:12:16:16 | query |
| marsdb.js:12:9:12:18 | query | marsdb.js:16:12:16:16 | query |
| marsdb.js:12:17:12:18 | {} | marsdb.js:12:9:12:18 | query |
| marsdb.js:13:17:13:24 | req.body | marsdb.js:13:17:13:30 | req.body.title |
| marsdb.js:13:17:13:24 | req.body | marsdb.js:13:17:13:30 | req.body.title |
| marsdb.js:13:17:13:30 | req.body.title | marsdb.js:12:9:12:18 | query |
| marsdb.js:13:17:13:30 | req.body.title | marsdb.js:12:17:12:18 | {} |
| marsdb.js:13:17:13:30 | req.body.title | marsdb.js:16:12:16:16 | query |
| marsdb.js:13:17:13:30 | req.body.title | marsdb.js:16:12:16:16 | query |
| minimongo.js:14:9:14:18 | query | minimongo.js:18:12:18:16 | query |
| minimongo.js:14:9:14:18 | query | minimongo.js:18:12:18:16 | query |
| minimongo.js:14:17:14:18 | {} | minimongo.js:14:9:14:18 | query |
| minimongo.js:15:17:15:24 | req.body | minimongo.js:15:17:15:30 | req.body.title |
| minimongo.js:15:17:15:24 | req.body | minimongo.js:15:17:15:30 | req.body.title |
| minimongo.js:15:17:15:30 | req.body.title | minimongo.js:14:9:14:18 | query |
| minimongo.js:15:17:15:30 | req.body.title | minimongo.js:14:17:14:18 | {} |
| minimongo.js:15:17:15:30 | req.body.title | minimongo.js:18:12:18:16 | query |
| minimongo.js:15:17:15:30 | req.body.title | minimongo.js:18:12:18:16 | query |
| mongodb.js:12:11:12:20 | query | mongodb.js:18:16:18:20 | query |
| mongodb.js:12:11:12:20 | query | mongodb.js:18:16:18:20 | query |
| mongodb.js:12:19:12:20 | {} | mongodb.js:12:11:12:20 | query |
@@ -371,6 +419,9 @@ edges
| tst.js:10:46:10:58 | req.params.id | tst.js:10:10:10:64 | 'SELECT ... d + '"' |
| tst.js:10:46:10:58 | req.params.id | tst.js:10:10:10:64 | 'SELECT ... d + '"' |
#select
| marsdb-flow-to.js:14:17:14:21 | query | marsdb-flow-to.js:11:17:11:24 | req.body | marsdb-flow-to.js:14:17:14:21 | query | This query depends on $@. | marsdb-flow-to.js:11:17:11:24 | req.body | a user-provided value |
| marsdb.js:16:12:16:16 | query | marsdb.js:13:17:13:24 | req.body | marsdb.js:16:12:16:16 | query | This query depends on $@. | marsdb.js:13:17:13:24 | req.body | a user-provided value |
| minimongo.js:18:12:18:16 | query | minimongo.js:15:17:15:24 | req.body | minimongo.js:18:12:18:16 | query | This query depends on $@. | minimongo.js:15:17:15:24 | req.body | a user-provided value |
| 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 |
| 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 |
| 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 |

View File

@@ -0,0 +1,9 @@
const MarsDB = require("marsdb");
const myDoc = new MarsDB.Collection("myDoc");
const db = {
myDoc
};
module.exports = db;

View File

@@ -0,0 +1,15 @@
const express = require("express"),
bodyParser = require("body-parser"),
db = require('./marsdb-flow-from');
const app = express();
app.use(bodyParser.urlencoded({ extended: true }));
app.post("/documents/find", (req, res) => {
const query = {};
query.title = req.body.title;
// NOT OK: query is tainted by user-provided object value
db.myDoc.find(query);
});

View File

@@ -0,0 +1,17 @@
const express = require("express"),
MarsDB = require("marsdb"),
bodyParser = require("body-parser");
let doc = new MarsDB.Collection("myDoc");
const app = express();
app.use(bodyParser.urlencoded({ extended: true }));
app.post("/documents/find", (req, res) => {
const query = {};
query.title = req.body.title;
// NOT OK: query is tainted by user-provided object value
doc.find(query);
});

View File

@@ -0,0 +1,19 @@
const express = require("express"),
minimongo = require("minimongo"),
bodyParser = require("body-parser");
var LocalDb = minimongo.MemoryDb,
db = new LocalDb(),
doc = db.myDocs;
const app = express();
app.use(bodyParser.urlencoded({ extended: true }));
app.post("/documents/find", (req, res) => {
const query = {};
query.title = req.body.title;
// NOT OK: query is tainted by user-provided object value
doc.find(query);
});