add a "../" removing taint-step for js/path-injection

This commit is contained in:
Erik Krogh Kristensen
2020-04-03 09:42:05 +02:00
parent 604731ba6b
commit e46cde17a1
4 changed files with 190 additions and 1 deletions

View File

@@ -206,6 +206,14 @@ module TaintedPath {
dstlabel.isNormalized()
)
or
// foo.replace(/(\.\.\/)*/, "") and similar
exists(DotDotSlashPrefixRemovingReplace call |
src = call.getInput() and
dst = call.getOutput() and
dstlabel.isAbsolute() and // result can be absolute
dstlabel.toAbsolute() = srclabel.toAbsolute() // preserves normalization status
)
or
// path.join()
exists(DataFlow::CallNode join, int n |
join = NodeJSLib::Path::moduleMember("join").getACall()

View File

@@ -225,7 +225,8 @@ module TaintedPath {
term.getAMatchedString() = "/" or
term.getAMatchedString() = "." or
term.getAMatchedString() = ".."
)
) and
not this instanceof DotDotSlashPrefixRemovingReplace
}
/**
@@ -239,6 +240,57 @@ module TaintedPath {
DataFlow::Node getOutput() { result = output }
}
/**
* A call that removes all instances of "../" in the prefix of the string.
*/
class DotDotSlashPrefixRemovingReplace extends DataFlow::CallNode {
DataFlow::Node input;
DataFlow::Node output;
DotDotSlashPrefixRemovingReplace() {
this.getCalleeName() = "replace" and
input = getReceiver() and
output = this and
exists(RegExpLiteral literal, RegExpTerm term |
getArgument(0).getALocalSource().asExpr() = literal and
(term instanceof RegExpStar or term instanceof RegExpPlus) and
term.getChild(0) = getADotDotSlashMatcher()
|
literal.getRoot() = term
or
exists(RegExpSequence seq | seq.getNumChild() = 2 and literal.getRoot() = seq |
seq.getChild(0) instanceof RegExpCaret and
seq.getChild(1) = term
)
)
}
/**
* Gets the input path to be sanitized.
*/
DataFlow::Node getInput() { result = input }
/**
* Gets the path where prefix "../" has been removed.
*/
DataFlow::Node getOutput() { result = output }
}
/**
* Gets a RegExpTerm that matches a variation of "../".
*/
private RegExpTerm getADotDotSlashMatcher() {
result.getAMatchedString() = "../"
or
exists(RegExpSequence seq | seq = result |
seq.getChild(0).getConstantValue() = "." and
seq.getChild(1).getConstantValue() = "." and
seq.getAChild().getAMatchedString() = "/"
)
or
exists(RegExpGroup group | result = group | group.getChild(0) = getADotDotSlashMatcher())
}
/**
* A call that removes all "." or ".." from a path, without also removing all forward slashes.
*/