more precise charpreds in taint steps

This commit is contained in:
Erik Krogh Kristensen
2020-03-26 14:22:10 +01:00
parent 0f70da2258
commit baf50c832c
2 changed files with 119 additions and 112 deletions

View File

@@ -8,13 +8,11 @@ module ArrayTaintTracking {
/** /**
* A taint propagating data flow edge caused by the builtin array functions. * A taint propagating data flow edge caused by the builtin array functions.
*/ */
private class ArrayFunctionTaintStep extends TaintTracking::AdditionalTaintStep { private class ArrayFunctionTaintStep extends TaintTracking::AdditionalTaintStep, DataFlow::CallNode {
DataFlow::CallNode call; ArrayFunctionTaintStep() { arrayFunctionTaintStep(_, _, this) }
ArrayFunctionTaintStep() { this = call }
override predicate step(DataFlow::Node pred, DataFlow::Node succ) { override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
arrayFunctionTaintStep(pred, succ, call) arrayFunctionTaintStep(pred, succ, this)
} }
} }

View File

@@ -230,14 +230,19 @@ module TaintTracking {
*/ */
private class HeapTaintStep extends AdditionalTaintStep { private class HeapTaintStep extends AdditionalTaintStep {
HeapTaintStep() { HeapTaintStep() {
this = DataFlow::valueNode(_) or heapStep(_, this)
this = DataFlow::parameterNode(_) or
this instanceof DataFlow::PropRead
} }
override predicate step(DataFlow::Node pred, DataFlow::Node succ) { override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
succ = this and heapStep(pred, succ) and succ = this
exists(Expr e, Expr f | e = this.asExpr() and f = pred.asExpr() | }
}
/**
* Holds if there is taint propagation through the heap from `pred` to `succ`.
*/
private predicate heapStep(DataFlow::Node pred, DataFlow::Node succ) {
exists(Expr e, Expr f | e = succ.asExpr() and f = pred.asExpr() |
// arrays with tainted elements and objects with tainted property names are tainted // arrays with tainted elements and objects with tainted property names are tainted
e.(ArrayExpr).getAnElement() = f e.(ArrayExpr).getAnElement() = f
or or
@@ -256,17 +261,14 @@ module TaintTracking {
) )
or or
// reading from a tainted object yields a tainted result // reading from a tainted object yields a tainted result
this = succ and
succ.(DataFlow::PropRead).getBase() = pred succ.(DataFlow::PropRead).getBase() = pred
or or
// iterating over a tainted iterator taints the loop variable // iterating over a tainted iterator taints the loop variable
exists(ForOfStmt fos | exists(ForOfStmt fos |
this = DataFlow::valueNode(fos.getIterationDomain()) and pred = DataFlow::valueNode(fos.getIterationDomain()) and
pred = this and
succ = DataFlow::lvalueNode(fos.getLValue()) succ = DataFlow::lvalueNode(fos.getLValue())
) )
} }
}
/** /**
* A taint propagating data flow edge through persistent storage. * A taint propagating data flow edge through persistent storage.
@@ -388,12 +390,21 @@ module TaintTracking {
* functions defined in the standard library. * functions defined in the standard library.
*/ */
private class StringManipulationTaintStep extends AdditionalTaintStep, DataFlow::ValueNode { private class StringManipulationTaintStep extends AdditionalTaintStep, DataFlow::ValueNode {
StringManipulationTaintStep() { stringManipulationStep(_, this) }
override predicate step(DataFlow::Node pred, DataFlow::Node succ) { override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
succ = this and succ = this and
( stringManipulationStep(pred, succ)
}
}
/**
* Holds if taint can propagate from `pred` to `succ` with a step related to string manipulation.
*/
private predicate stringManipulationStep(DataFlow::Node pred, DataFlow::ValueNode succ) {
// string operations that propagate taint // string operations that propagate taint
exists(string name | name = astNode.(MethodCallExpr).getMethodName() | exists(string name | name = succ.getAstNode().(MethodCallExpr).getMethodName() |
pred.asExpr() = astNode.(MethodCallExpr).getReceiver() and pred.asExpr() = succ.getAstNode().(MethodCallExpr).getReceiver() and
( (
// sorted, interesting, properties of String.prototype // sorted, interesting, properties of String.prototype
name = "anchor" or name = "anchor" or
@@ -432,7 +443,7 @@ module TaintTracking {
name = "join" name = "join"
) )
or or
exists(int i | pred.asExpr() = astNode.(MethodCallExpr).getArgument(i) | exists(int i | pred.asExpr() = succ.getAstNode().(MethodCallExpr).getArgument(i) |
name = "concat" name = "concat"
or or
name = "replace" and i = 1 name = "replace" and i = 1
@@ -441,21 +452,21 @@ module TaintTracking {
or or
// standard library constructors that propagate taint: `RegExp` and `String` // standard library constructors that propagate taint: `RegExp` and `String`
exists(DataFlow::InvokeNode invk, string gv | gv = "RegExp" or gv = "String" | exists(DataFlow::InvokeNode invk, string gv | gv = "RegExp" or gv = "String" |
this = invk and succ = invk and
invk = DataFlow::globalVarRef(gv).getAnInvocation() and invk = DataFlow::globalVarRef(gv).getAnInvocation() and
pred = invk.getArgument(0) pred = invk.getArgument(0)
) )
or or
// String.fromCharCode and String.fromCodePoint // String.fromCharCode and String.fromCodePoint
exists(int i, MethodCallExpr mce | exists(int i, MethodCallExpr mce |
mce = astNode and mce = succ.getAstNode() and
pred.asExpr() = mce.getArgument(i) and pred.asExpr() = mce.getArgument(i) and
(mce.getMethodName() = "fromCharCode" or mce.getMethodName() = "fromCodePoint") (mce.getMethodName() = "fromCharCode" or mce.getMethodName() = "fromCodePoint")
) )
or or
// `(encode|decode)URI(Component)?` propagate taint // `(encode|decode)URI(Component)?` propagate taint
exists(DataFlow::CallNode c, string name | exists(DataFlow::CallNode c, string name |
this = c and succ = c and
c = DataFlow::globalVarRef(name).getACall() and c = DataFlow::globalVarRef(name).getACall() and
pred = c.getArgument(0) pred = c.getArgument(0)
| |
@@ -464,8 +475,6 @@ module TaintTracking {
name = "encodeURIComponent" or name = "encodeURIComponent" or
name = "decodeURIComponent" name = "decodeURIComponent"
) )
)
}
} }
/** /**