JavaScript: Add tests for data-flow tutorial.

This commit is contained in:
Max Schaefer
2019-06-07 14:33:26 +01:00
parent f7a092882b
commit 398ee0c133
23 changed files with 235 additions and 0 deletions

View File

@@ -0,0 +1,3 @@
| test1.js:13:16:13:30 | process.argv[2] | test1.js:6:15:6:15 | p |
| test2.js:20:16:20:30 | process.argv[2] | test2.js:13:15:13:15 | p |
| test3.js:19:16:19:30 | process.argv[2] | test3.js:12:15:12:15 | p |

View File

@@ -0,0 +1,17 @@
import javascript
class CommandLineFileNameConfiguration extends TaintTracking::Configuration {
CommandLineFileNameConfiguration() { this = "CommandLineFileNameConfiguration" }
override predicate isSource(DataFlow::Node source) {
DataFlow::globalVarRef("process").getAPropertyRead("argv").getAPropertyRead() = source
}
override predicate isSink(DataFlow::Node sink) {
DataFlow::moduleMember("fs", "readFile").getACall().getArgument(0) = sink
}
}
from CommandLineFileNameConfiguration cfg, DataFlow::Node source, DataFlow::Node sink
where cfg.hasFlow(source, sink)
select source, sink

View File

@@ -0,0 +1,2 @@
| test1.js:13:16:13:30 | process.argv[2] | test1.js:6:15:6:15 | p |
| test3.js:19:16:19:30 | process.argv[2] | test3.js:12:15:12:15 | p |

View File

@@ -0,0 +1,21 @@
import javascript
class CommandLineFileNameConfiguration extends TaintTracking::Configuration {
CommandLineFileNameConfiguration() { this = "CommandLineFileNameConfiguration" }
override predicate isSource(DataFlow::Node source) {
DataFlow::globalVarRef("process").getAPropertyRead("argv").getAPropertyRead() = source
}
override predicate isSink(DataFlow::Node sink) {
DataFlow::moduleMember("fs", "readFile").getACall().getArgument(0) = sink
}
override predicate isSanitizer(DataFlow::Node nd) {
nd.(DataFlow::CallNode).getCalleeName() = "checkPath"
}
}
from CommandLineFileNameConfiguration cfg, DataFlow::Node source, DataFlow::Node sink
where cfg.hasFlow(source, sink)
select source, sink

View File

@@ -0,0 +1,2 @@
| test1.js:13:16:13:30 | process.argv[2] | test1.js:6:15:6:15 | p |
| test2.js:20:16:20:30 | process.argv[2] | test2.js:13:15:13:15 | p |

View File

@@ -0,0 +1,30 @@
import javascript
class CheckPathSanitizerGuard extends TaintTracking::SanitizerGuardNode, DataFlow::CallNode {
CheckPathSanitizerGuard() { this.getCalleeName() = "checkPath" }
override predicate sanitizes(boolean outcome, Expr e) {
outcome = true and
e = getArgument(0).asExpr()
}
}
class CommandLineFileNameConfiguration extends TaintTracking::Configuration {
CommandLineFileNameConfiguration() { this = "CommandLineFileNameConfiguration" }
override predicate isSource(DataFlow::Node source) {
DataFlow::globalVarRef("process").getAPropertyRead("argv").getAPropertyRead() = source
}
override predicate isSink(DataFlow::Node sink) {
DataFlow::moduleMember("fs", "readFile").getACall().getArgument(0) = sink
}
override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode nd) {
nd instanceof CheckPathSanitizerGuard
}
}
from CommandLineFileNameConfiguration cfg, DataFlow::Node source, DataFlow::Node sink
where cfg.hasFlow(source, sink)
select source, sink

View File

@@ -0,0 +1,4 @@
| test1.js:13:16:13:30 | process.argv[2] | test1.js:6:15:6:15 | p |
| test2.js:20:16:20:30 | process.argv[2] | test2.js:13:15:13:15 | p |
| test3.js:19:16:19:30 | process.argv[2] | test3.js:12:15:12:15 | p |
| test4.js:14:16:14:30 | process.argv[2] | test4.js:7:13:7:13 | p |

View File

@@ -0,0 +1,25 @@
import javascript
class CommandLineFileNameConfiguration extends TaintTracking::Configuration {
CommandLineFileNameConfiguration() { this = "CommandLineFileNameConfiguration" }
override predicate isSource(DataFlow::Node source) {
DataFlow::globalVarRef("process").getAPropertyRead("argv").getAPropertyRead() = source
}
override predicate isSink(DataFlow::Node sink) {
DataFlow::moduleMember("fs", "readFile").getACall().getArgument(0) = sink
}
override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) {
exists(DataFlow::CallNode c |
c = DataFlow::moduleImport("resolve-symlinks").getACall() and
pred = c.getArgument(0) and
succ = c
)
}
}
from CommandLineFileNameConfiguration cfg, DataFlow::Node source, DataFlow::Node sink
where cfg.hasFlow(source, sink)
select source, sink

View File

@@ -0,0 +1,4 @@
| test1.js:13:16:13:30 | process.argv[2] | test1.js:6:15:6:15 | p |
| test2.js:20:16:20:30 | process.argv[2] | test2.js:13:15:13:15 | p |
| test3.js:19:16:19:30 | process.argv[2] | test3.js:12:15:12:15 | p |
| test4.js:14:16:14:30 | process.argv[2] | test4.js:7:13:7:13 | p |

View File

@@ -0,0 +1,26 @@
import javascript
class StepThroughResolveSymlinks extends TaintTracking::AdditionalTaintStep, DataFlow::CallNode {
StepThroughResolveSymlinks() { this = DataFlow::moduleImport("resolve-symlinks").getACall() }
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
pred = this.getArgument(0) and
succ = this
}
}
class CommandLineFileNameConfiguration extends TaintTracking::Configuration {
CommandLineFileNameConfiguration() { this = "CommandLineFileNameConfiguration" }
override predicate isSource(DataFlow::Node source) {
DataFlow::globalVarRef("process").getAPropertyRead("argv").getAPropertyRead() = source
}
override predicate isSink(DataFlow::Node sink) {
DataFlow::moduleMember("fs", "readFile").getACall().getArgument(0) = sink
}
}
from CommandLineFileNameConfiguration cfg, DataFlow::Node source, DataFlow::Node sink
where cfg.hasFlow(source, sink)
select source, sink

View File

@@ -0,0 +1,13 @@
const fs = require('fs'),
path = require('path');
function readFileHelper(p) { // #2
p = path.resolve(p); // #3
fs.readFile(p, // #4
'utf8', (err, data) => {
if (err) throw err;
console.log(data);
});
}
readFileHelper(process.argv[2]); // #1

View File

@@ -0,0 +1,20 @@
const fs = require('fs'),
path = require('path');
function checkPath(p) {
p = path.resolve(p);
if (!p.startsWith(process.cwd() + path.sep))
throw new Error("Invalid path " + p);
return p;
}
function readFileHelper(p) {
p = checkPath(p);
fs.readFile(p,
'utf8', (err, data) => {
if (err) throw err;
console.log(data);
});
}
readFileHelper(process.argv[2]);

View File

@@ -0,0 +1,19 @@
const fs = require('fs'),
path = require('path');
function checkPath(p) {
p = path.resolve(p);
return p.startsWith(process.cwd() + path.sep);
}
function readFileHelper(p) {
if (!checkPath(p))
return;
fs.readFile(p,
'utf8', (err, data) => {
if (err) throw err;
console.log(data);
});
}
readFileHelper(process.argv[2]);

View File

@@ -0,0 +1,14 @@
const fs = require('fs'),
path = require('path'),
resolveSymlinks = require('resolve-symlinks');
function readFileHelper(p) {
p = resolveSymlinks(p);
fs.readFile(p,
'utf8', (err, data) => {
if (err) throw err;
console.log(data);
});
}
readFileHelper(process.argv[2]);

View File

@@ -0,0 +1,3 @@
| test.js:4:5:4:22 | firstArg |
| test.js:4:16:4:22 | args[2] |
| test.js:5:13:5:20 | firstArg |

View File

@@ -0,0 +1,7 @@
import javascript
from DataFlow::MethodCallNode readFile, DataFlow::Node source
where
readFile.getMethodName() = "readFile" and
source.getASuccessor*() = readFile.getArgument(0)
select source

View File

@@ -0,0 +1 @@
| test.js:4:16:4:22 | args[2] |

View File

@@ -0,0 +1,3 @@
import javascript
select DataFlow::globalVarRef("process").getAPropertyRead("argv").getAPropertyReference()

View File

@@ -0,0 +1 @@
| test.js:5:1:8:2 | fs.read ... ta);\\n}) |

View File

@@ -0,0 +1,3 @@
import javascript
select DataFlow::moduleMember("fs", "readFile").getACall()

View File

@@ -0,0 +1 @@
| test.js:4:16:4:22 | args[2] | test.js:5:1:8:2 | fs.read ... ta);\\n}) |

View File

@@ -0,0 +1,8 @@
import javascript
from DataFlow::SourceNode arg, DataFlow::CallNode call
where
arg = DataFlow::globalVarRef("process").getAPropertyRead("argv").getAPropertyReference() and
call = DataFlow::moduleMember("fs", "readFile").getACall() and
arg.flowsTo(call.getArgument(0))
select arg, call

View File

@@ -0,0 +1,8 @@
var fs = require('fs');
var args = process.argv;
var firstArg = args[2];
fs.readFile(firstArg, 'utf8', (err, data) => {
if (err) throw err;
console.log(data);
});