JavaScript: Add partial model for opener.

3.5M weekly downloads.

Note that we do not treat the first argument as a command-injection sink. While it is possible to inject commands that way, it is more likely to cause false positives where the user input is concatenated with some prefix that makes the opening heuristic decide to treat it as a URL.
This commit is contained in:
Max Schaefer
2020-07-27 11:42:32 +01:00
parent 9aa26fa4bc
commit 91762ec274
4 changed files with 23 additions and 1 deletions

View File

@@ -19,6 +19,7 @@
- [mssql](https://www.npmjs.com/package/mssql)
- [mysql](https://www.npmjs.com/package/mysql)
- [npmlog](https://www.npmjs.com/package/npmlog)
- [opener](https://www.npmjs.com/package/opener)
- [pg](https://www.npmjs.com/package/pg)
- [sequelize](https://www.npmjs.com/package/sequelize)
- [spanner](https://www.npmjs.com/package/spanner)

View File

@@ -135,3 +135,15 @@ private class RemoteCommandExecutor extends SystemCommandExecution, DataFlow::In
override DataFlow::Node getOptionsArg() { none() }
}
private class Opener extends SystemCommandExecution, DataFlow::InvokeNode {
Opener() { this = DataFlow::moduleImport("opener").getACall() }
override DataFlow::Node getACommandArgument() { result = getOptionArgument(1, "command") }
override predicate isShellInterpreted(DataFlow::Node arg) { none() }
override predicate isSync() { none() }
override DataFlow::Node getOptionsArg() { none() }
}

View File

@@ -113,6 +113,8 @@ nodes
| other.js:28:27:28:29 | cmd |
| other.js:30:33:30:35 | cmd |
| other.js:30:33:30:35 | cmd |
| other.js:34:44:34:46 | cmd |
| other.js:34:44:34:46 | cmd |
| third-party-command-injection.js:5:20:5:26 | command |
| third-party-command-injection.js:5:20:5:26 | command |
| third-party-command-injection.js:6:21:6:27 | command |
@@ -221,6 +223,8 @@ edges
| other.js:5:9:5:49 | cmd | other.js:28:27:28:29 | cmd |
| other.js:5:9:5:49 | cmd | other.js:30:33:30:35 | cmd |
| other.js:5:9:5:49 | cmd | other.js:30:33:30:35 | cmd |
| other.js:5:9:5:49 | cmd | other.js:34:44:34:46 | cmd |
| other.js:5:9:5:49 | cmd | other.js:34:44:34:46 | cmd |
| other.js:5:15:5:38 | url.par ... , true) | other.js:5:15:5:44 | url.par ... ).query |
| other.js:5:15:5:44 | url.par ... ).query | other.js:5:15:5:49 | url.par ... ry.path |
| other.js:5:15:5:49 | url.par ... ry.path | other.js:5:9:5:49 | cmd |
@@ -271,4 +275,5 @@ edges
| other.js:26:34:26:36 | cmd | other.js:5:25:5:31 | req.url | other.js:26:34:26:36 | cmd | This command depends on $@. | other.js:5:25:5:31 | req.url | a user-provided value |
| other.js:28:27:28:29 | cmd | other.js:5:25:5:31 | req.url | other.js:28:27:28:29 | cmd | This command depends on $@. | other.js:5:25:5:31 | req.url | a user-provided value |
| other.js:30:33:30:35 | cmd | other.js:5:25:5:31 | req.url | other.js:30:33:30:35 | cmd | This command depends on $@. | other.js:5:25:5:31 | req.url | a user-provided value |
| other.js:34:44:34:46 | cmd | other.js:5:25:5:31 | req.url | other.js:34:44:34:46 | cmd | This command depends on $@. | other.js:5:25:5:31 | req.url | a user-provided value |
| third-party-command-injection.js:6:21:6:27 | command | third-party-command-injection.js:5:20:5:26 | command | third-party-command-injection.js:6:21:6:27 | command | This command depends on $@. | third-party-command-injection.js:5:20:5:26 | command | a server-provided value |

View File

@@ -1,7 +1,7 @@
var http = require("http"),
url = require("url");
var server = http.createServer(function(req, res) {
var server = http.createServer(function (req, res) {
let cmd = url.parse(req.url, true).query.path;
require("cross-spawn").sync(cmd); // NOT OK
@@ -28,4 +28,8 @@ var server = http.createServer(function(req, res) {
require("execa").node(cmd); // NOT OK
require("foreground-child")(cmd); // NOT OK
const opener = require("opener");
opener("http://github.com/" + url.parse(req.url, true).query.user); // OK
opener("http://github.com", { command: cmd }); // NOT OK
});