add taint-step to XML parsers

This commit is contained in:
Erik Krogh Kristensen
2021-02-04 17:08:18 +01:00
parent 1c43505d30
commit 44ca2e26a6
3 changed files with 33 additions and 3 deletions

View File

@@ -25,6 +25,9 @@ module XML {
/** Holds if this call to the XML parser resolves entities of the given `kind`. */
abstract predicate resolvesEntities(EntityKind kind);
/** Gets a reference to a value resulting from parsing the XML. */
js::DataFlow::Node getAResult() { none() }
}
/**
@@ -98,10 +101,11 @@ module XML {
* An invocation of `expat.Parser.parse` or `expat.Parser.write`.
*/
class ExpatParserInvocation extends ParserInvocation {
js::DataFlow::NewNode parser;
ExpatParserInvocation() {
exists(string m | m = "parse" or m = "write" |
this = moduleMethodCall("node-expat", "Parser", m)
)
parser = js::DataFlow::moduleMember("node-expat", "Parser").getAnInstantiation() and
this = parser.getAMemberCall(["parse", "write"]).asExpr()
}
override js::Expr getSourceArgument() { result = getArgument(0) }
@@ -110,6 +114,10 @@ module XML {
// only internal entities are resolved by default
kind = InternalEntity()
}
override js::DataFlow::Node getAResult() {
result = parser.getAMemberCall("on").getABoundCallbackParameter(1, _)
}
}
/**
@@ -160,4 +168,15 @@ module XML {
override predicate resolvesEntities(XML::EntityKind kind) { kind = InternalEntity() }
}
private class XMLParserTaintStep extends js::TaintTracking::AdditionalTaintStep {
XML::ParserInvocation parser;
XMLParserTaintStep() { this.asExpr() = parser }
override predicate step(js::DataFlow::Node pred, js::DataFlow::Node succ) {
pred.asExpr() = parser.getSourceArgument() and
succ = parser.getAResult()
}
}
}

View File

@@ -145,3 +145,4 @@ typeInferenceMismatch
| tst.js:2:13:2:20 | source() | tst.js:45:10:45:24 | x.map(x2 => x2) |
| tst.js:2:13:2:20 | source() | tst.js:47:10:47:30 | Buffer. ... 'hex') |
| tst.js:2:13:2:20 | source() | tst.js:48:10:48:22 | new Buffer(x) |
| xml.js:5:18:5:25 | source() | xml.js:8:14:8:17 | text |

View File

@@ -0,0 +1,10 @@
(function () {
var Parser = require("node-expat").Parser
var parser = new Parser();
parser.write(source());
parser.on("text", text => {
sink(text); // NOT OK
});
})();