Add guard to taint tracking configuration

This commit is contained in:
Michael Hohn
2023-11-30 13:57:39 -08:00
committed by =Michael Hohn
parent 788d772556
commit 01524f7432

View File

@@ -17,6 +17,7 @@ import DataFlow as DF
// ua.setValue('status',value); //: taint step // ua.setValue('status',value); //: taint step
// ua.update(); //: sink (if from source 2) // ua.update(); //: sink (if from source 2)
// //
// var value = this.getParameter('value'); //: source 1 // var value = this.getParameter('value'); //: source 1
class ParameterSource extends CallExpr { class ParameterSource extends CallExpr {
ParameterSource() { ParameterSource() {
@@ -41,18 +42,36 @@ predicate setValueTaintStep(DataFlow::Node pred, DataFlow::Node succ) {
// //
// Using control flow: // Using control flow:
// 1. without sanitizer // 1. without sanitizer
// gr.getASuccessor+() = postgr and gr.getASuccessor+() = postgr and
// succ.asExpr() = postgr succ.asExpr() = postgr
// //
// 2. with recursive predicate, no sanitizer // 2. with recursive predicate, no sanitizer
recursiveSuccessor(gr, postgr) and // recursiveSuccessor(gr, postgr) and
succ.asExpr() = postgr // succ.asExpr() = postgr
// // 3. with recursive predicate, with sanitizer // 3. with recursive predicate, with sanitizer
// sanitizerCheckedSuccessor(gr, postgr) and // sanitizerCheckedSuccessor(gr, postgr) and
// succ.asExpr() = postgr // succ.asExpr() = postgr
) )
} }
// Def-Use special handling:
// - Include sanitizer check when flagging successive object member calls in taint
// step.
// - Stop at
// ua.safeToWrite()
predicate sanitizerCheckedSuccessor(ControlFlowNode gr, ControlFlowNode postgr) {
gr.getASuccessor() = postgr and
not inSafeToWrite(postgr)
or
exists(ControlFlowNode p |
sanitizerCheckedSuccessor(gr, p) and
not gr.getASuccessor() = postgr and
p.getASuccessor() = postgr
)
// The final postgr needs to be a VarAccess for this query, but for the
// recursion we need to be able to traverse expressions.
}
predicate foo(VarAccess gr, VarAccess postgr) { predicate foo(VarAccess gr, VarAccess postgr) {
exists(DotExpr temp, MethodCallExpr mce | exists(DotExpr temp, MethodCallExpr mce |
temp.getPropertyName() = "setValue" and temp.getPropertyName() = "setValue" and
@@ -71,8 +90,31 @@ predicate foo1(Expr gr, Expr postgr) {
) )
} }
// Def-Use special handling: predicate foo2(Expr gr, Expr postgr) {
// Include sanitizer check when flagging successive object member calls in taint step exists(DotExpr temp, MethodCallExpr mce |
temp.getPropertyName() = "setValue" and
mce.getReceiver() = temp.getBase() and
gr = mce.getReceiver() and
sanitizerCheckedSuccessor(gr, postgr)
)
}
predicate inSafeToWrite(ControlFlowNode p) {
exists(
// DotExpr temp, MethodCallExpr mce,
IfStmt if_
|
// XX:
if_.getAChild+().getFirstControlFlowNode() = p
// and
// temp.getPropertyName() = "safeToWrite" and
// p = mce.getReceiver() and
// p = temp.getBase()
)
}
// Preparation for including a sanitizer check when flagging successive object
// member calls in taint step
predicate recursiveSuccessor(ControlFlowNode gr, ControlFlowNode postgr) { predicate recursiveSuccessor(ControlFlowNode gr, ControlFlowNode postgr) {
gr.getASuccessor() = postgr gr.getASuccessor() = postgr
or or
@@ -116,6 +158,10 @@ class FromRequestToGrUpdate extends TaintTracking::Configuration {
setValueTaintStep(pred, succ) setValueTaintStep(pred, succ)
} }
override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode nd) {
nd instanceof CanWriteGuard
}
override predicate isSink(DataFlow::Node sink) { override predicate isSink(DataFlow::Node sink) {
exists(VarRef grUpdate | exists(VarRef grUpdate |
sink.asExpr() = recordUpdate() and sink.asExpr() = recordUpdate() and
@@ -127,6 +173,17 @@ class FromRequestToGrUpdate extends TaintTracking::Configuration {
} }
} }
class CanWriteGuard extends TaintTracking::SanitizerGuardNode, DataFlow::CallNode {
CanWriteGuard() { this.getCalleeName() = "safeToWrite" }
override predicate sanitizes(boolean outcome, Expr e) {
// outcome is the result of the conditional (the true or false branch)
outcome = true and
e = this.getReceiver().asExpr()
// or e.getASuccessor+() = this.getReceiver().asExpr()
}
}
from FromRequestToGrUpdate dataflow, DataFlow::PathNode source, DataFlow::PathNode sink from FromRequestToGrUpdate dataflow, DataFlow::PathNode source, DataFlow::PathNode sink
where dataflow.hasFlowPath(source, sink) where dataflow.hasFlowPath(source, sink)
select sink, source, sink, "Data flow from $@ to $@.", source, source.toString(), sink, select sink, source, sink, "Data flow from $@ to $@.", source, source.toString(), sink,