Compare commits

...

2 Commits

Author SHA1 Message Date
Esben Sparre Andreasen
3248fc2e1b make ATM anti sink model for dojo.require 2021-12-08 14:36:51 +01:00
Esben Sparre Andreasen
55c35659b5 add file write model for express-fileupload mv 2021-12-08 13:26:34 +01:00
5 changed files with 55 additions and 1 deletions

View File

@@ -204,5 +204,8 @@ predicate isOtherModeledArgument(DataFlow::Node n, FilteringReason reason) {
call.getCalleeName() = "next" and
exists(DataFlow::FunctionNode f | call = f.getLastParameter().getACall()) and
reason instanceof NextFunctionCallReason
or
call = DataFlow::globalVarRef("dojo").getAPropertyRead("require").getACall() and
reason instanceof DojoRequireReason
)
}

View File

@@ -29,7 +29,8 @@ newtype TFilteringReason =
TArgumentToArrayReason() or
TArgumentToBuiltinGlobalVarRefReason() or
TConstantReceiverReason() or
TBuiltinCallNameReason()
TBuiltinCallNameReason() or
TDojoRequireReason()
/** A reason why a particular endpoint was filtered out by the endpoint filters. */
abstract class FilteringReason extends TFilteringReason {
@@ -194,3 +195,9 @@ class BuiltinCallNameReason extends NotASinkReason, TBuiltinCallNameReason {
override int getEncoding() { result = 27 }
}
class DojoRequireReason extends NotASinkReason, TDojoRequireReason {
override string getDescription() { result = "DojoRequire" }
override int getEncoding() { result = 28 }
}

View File

@@ -226,3 +226,30 @@ module ExpressLibraries {
predicate producesUserControlledObjects() { isJson() or isExtendedUrlEncoded() }
}
}
/**
* Provides classes for working with the `express-fileupload` package (https://github.com/richardgirges/express-fileupload);
*/
module FileUpload {
/** Gets a data flow node referring to `req.files`. */
private DataFlow::SourceNode filesRef(Express::RequestSource req, DataFlow::TypeTracker t) {
t.start() and
result = req.ref().getAPropertyRead("files")
or
exists(DataFlow::TypeTracker t2 | result = filesRef(req, t2).track(t2, t))
}
/**
* A call to `req.files.<name>.mv`
*/
class Move extends FileSystemWriteAccess, DataFlow::MethodCallNode {
Move() {
exists(DataFlow::moduleImport("express-fileupload")) and
this = filesRef(_, DataFlow::TypeTracker::end()).getAPropertyRead().getAMethodCall("mv")
}
override DataFlow::Node getAPathArgument() { result = getArgument(0) }
override DataFlow::Node getADataNode() { none() }
}
}

View File

@@ -1535,6 +1535,12 @@ nodes
| TaintedPath.js:214:35:214:38 | path |
| TaintedPath.js:214:35:214:38 | path |
| TaintedPath.js:214:35:214:38 | path |
| express.js:8:20:8:32 | req.query.bar |
| express.js:8:20:8:32 | req.query.bar |
| express.js:8:20:8:32 | req.query.bar |
| express.js:8:20:8:32 | req.query.bar |
| express.js:8:20:8:32 | req.query.bar |
| express.js:8:20:8:32 | req.query.bar |
| normalizedPaths.js:11:7:11:27 | path |
| normalizedPaths.js:11:7:11:27 | path |
| normalizedPaths.js:11:7:11:27 | path |
@@ -6321,6 +6327,7 @@ edges
| TaintedPath.js:211:24:211:30 | req.url | TaintedPath.js:211:14:211:37 | url.par ... , true) |
| TaintedPath.js:211:24:211:30 | req.url | TaintedPath.js:211:14:211:37 | url.par ... , true) |
| TaintedPath.js:211:24:211:30 | req.url | TaintedPath.js:211:14:211:37 | url.par ... , true) |
| express.js:8:20:8:32 | req.query.bar | express.js:8:20:8:32 | req.query.bar |
| normalizedPaths.js:11:7:11:27 | path | normalizedPaths.js:13:19:13:22 | path |
| normalizedPaths.js:11:7:11:27 | path | normalizedPaths.js:13:19:13:22 | path |
| normalizedPaths.js:11:7:11:27 | path | normalizedPaths.js:13:19:13:22 | path |
@@ -9638,6 +9645,7 @@ edges
| TaintedPath.js:212:31:212:34 | path | TaintedPath.js:211:24:211:30 | req.url | TaintedPath.js:212:31:212:34 | path | This path depends on $@. | TaintedPath.js:211:24:211:30 | req.url | a user-provided value |
| TaintedPath.js:213:45:213:48 | path | TaintedPath.js:211:24:211:30 | req.url | TaintedPath.js:213:45:213:48 | path | This path depends on $@. | TaintedPath.js:211:24:211:30 | req.url | a user-provided value |
| TaintedPath.js:214:35:214:38 | path | TaintedPath.js:211:24:211:30 | req.url | TaintedPath.js:214:35:214:38 | path | This path depends on $@. | TaintedPath.js:211:24:211:30 | req.url | a user-provided value |
| express.js:8:20:8:32 | req.query.bar | express.js:8:20:8:32 | req.query.bar | express.js:8:20:8:32 | req.query.bar | This path depends on $@. | express.js:8:20:8:32 | req.query.bar | a user-provided value |
| normalizedPaths.js:13:19:13:22 | path | normalizedPaths.js:11:14:11:27 | req.query.path | normalizedPaths.js:13:19:13:22 | path | This path depends on $@. | normalizedPaths.js:11:14:11:27 | req.query.path | a user-provided value |
| normalizedPaths.js:14:19:14:29 | './' + path | normalizedPaths.js:11:14:11:27 | req.query.path | normalizedPaths.js:14:19:14:29 | './' + path | This path depends on $@. | normalizedPaths.js:11:14:11:27 | req.query.path | a user-provided value |
| normalizedPaths.js:15:19:15:38 | path + '/index.html' | normalizedPaths.js:11:14:11:27 | req.query.path | normalizedPaths.js:15:19:15:38 | path + '/index.html' | This path depends on $@. | normalizedPaths.js:11:14:11:27 | req.query.path | a user-provided value |

View File

@@ -0,0 +1,9 @@
var express = require("express"),
fileUpload = require("express-fileupload");
let app = express();
app.use(fileUpload());
app.get("/some/path", function (req, res) {
req.files.foo.mv(req.query.bar);
});