1414
1515import go
1616import semmle.go.security.OpenUrlRedirectCustomizations
17- import DataFlow:: PathGraph
1817
1918StringOps:: HasPrefix checkForLeadingSlash ( SsaWithFields v ) {
2019 exists ( DataFlow:: Node substr |
@@ -91,29 +90,27 @@ predicate urlPath(DataFlow::Node nd) {
9190 )
9291}
9392
94- class Configuration extends TaintTracking:: Configuration {
95- Configuration ( ) { this = "BadRedirectCheck" }
96-
97- override predicate isSource ( DataFlow:: Node source ) { this .isCheckedSource ( source , _) }
93+ module Config implements DataFlow:: ConfigSig {
94+ predicate isSource ( DataFlow:: Node source ) { isCheckedSource ( source , _) }
9895
9996 /**
10097 * Holds if `source` is the first node that flows into a use of a variable that is checked by a
10198 * bad redirect check `check`..
10299 */
103- predicate isCheckedSource ( DataFlow:: Node source , DataFlow:: Node check ) {
100+ additional predicate isCheckedSource ( DataFlow:: Node source , DataFlow:: Node check ) {
104101 exists ( SsaWithFields v |
105102 DataFlow:: localFlow ( source , v .getAUse ( ) ) and
106103 not exists ( source .getAPredecessor ( ) ) and
107104 isBadRedirectCheckOrWrapper ( check , v )
108105 )
109106 }
110107
111- override predicate isAdditionalTaintStep ( DataFlow:: Node pred , DataFlow:: Node succ ) {
108+ predicate isAdditionalFlowStep ( DataFlow:: Node node1 , DataFlow:: Node node2 ) {
112109 // this is very over-approximate, because most filtering is done by the isSource predicate
113- exists ( Write w | w .writesField ( succ , _, pred ) )
110+ exists ( Write w | w .writesField ( node2 , _, node1 ) )
114111 }
115112
116- override predicate isSanitizerOut ( DataFlow:: Node node ) {
113+ predicate isBarrierOut ( DataFlow:: Node node ) {
117114 // assume this value is safe if something is prepended to it.
118115 exists ( StringOps:: Concatenation conc , int i , int j | i < j |
119116 node = conc .getOperand ( j ) and
@@ -125,9 +122,11 @@ class Configuration extends TaintTracking::Configuration {
125122 )
126123 }
127124
128- override predicate isSink ( DataFlow:: Node sink ) { sink instanceof OpenUrlRedirect:: Sink }
125+ predicate isSink ( DataFlow:: Node sink ) { sink instanceof OpenUrlRedirect:: Sink }
129126}
130127
128+ module Flow = TaintTracking:: Global< Config > ;
129+
131130/**
132131 * Holds there is a check `check` that is a bad redirect check, and `v` is either
133132 * checked directly by `check` or checked by a function that contains `check`.
@@ -168,10 +167,12 @@ predicate isBadRedirectCheckWrapper(DataFlow::Node check, FuncDef f, FunctionInp
168167 )
169168}
170169
171- from Configuration cfg , DataFlow:: PathNode source , DataFlow:: PathNode sink , DataFlow:: Node check
170+ import Flow:: PathGraph
171+
172+ from Flow:: PathNode source , Flow:: PathNode sink , DataFlow:: Node check
172173where
173- cfg . isCheckedSource ( source .getNode ( ) , check ) and
174- cfg . hasFlowPath ( source , sink )
174+ Config :: isCheckedSource ( source .getNode ( ) , check ) and
175+ Flow :: flowPath ( source , sink )
175176select check , source , sink ,
176177 "This is a check that $@, which flows into a $@, has a leading slash, but not that it does not have '/' or '\\' in its second position." ,
177178 source .getNode ( ) , "this value" , sink .getNode ( ) , "redirect"
0 commit comments