mirror of
https://github.com/hohn/codeql-javascript-multiflow.git
synced 2025-12-16 12:03:03 +01:00
Add guard to taint tracking configuration
This commit is contained in:
committed by
=Michael Hohn
parent
788d772556
commit
01524f7432
@@ -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,
|
||||||
|
|||||||
Reference in New Issue
Block a user