@@ -19,7 +19,12 @@ module ClientSideUrlRedirect {
19
19
/**
20
20
* A data flow sink for unvalidated URL redirect vulnerabilities.
21
21
*/
22
- abstract class Sink extends DataFlow:: Node { }
22
+ abstract class Sink extends DataFlow:: Node {
23
+ /** Holds if the sink can execute JavaScript code in the current context. */
24
+ predicate isXSSSink ( ) {
25
+ none ( ) // overwritten in subclasses
26
+ }
27
+ }
23
28
24
29
/**
25
30
* A sanitizer for unvalidated URL redirect vulnerabilities.
@@ -84,37 +89,46 @@ module ClientSideUrlRedirect {
84
89
* A sink which is used to set the window location.
85
90
*/
86
91
class LocationSink extends Sink , DataFlow:: ValueNode {
92
+ boolean xss ;
93
+
87
94
LocationSink ( ) {
88
95
// A call to a `window.navigate` or `window.open`
89
96
exists ( string name | name = [ "navigate" , "open" , "openDialog" , "showModalDialog" ] |
90
97
this = DataFlow:: globalVarRef ( name ) .getACall ( ) .getArgument ( 0 )
91
- )
98
+ ) and
99
+ xss = false
92
100
or
93
101
// A call to `location.replace` or `location.assign`
94
102
exists ( DataFlow:: MethodCallNode locationCall , string name |
95
103
locationCall = DOM:: locationRef ( ) .getAMethodCall ( name ) and
96
104
this = locationCall .getArgument ( 0 )
97
105
|
98
106
name = [ "replace" , "assign" ]
99
- )
107
+ ) and
108
+ xss = true
100
109
or
101
110
// An assignment to `location`
102
- exists ( Assignment assgn | isLocation ( assgn .getTarget ( ) ) and astNode = assgn .getRhs ( ) )
111
+ exists ( Assignment assgn | isLocation ( assgn .getTarget ( ) ) and astNode = assgn .getRhs ( ) ) and
112
+ xss = true
103
113
or
104
114
// An assignment to `location.href`, `location.protocol` or `location.hostname`
105
115
exists ( DataFlow:: PropWrite pw , string propName |
106
116
pw = DOM:: locationRef ( ) .getAPropertyWrite ( propName ) and
107
117
this = pw .getRhs ( )
108
118
|
109
- propName = [ "href" , "protocol" , "hostname" ]
119
+ propName = [ "href" , "protocol" , "hostname" ] and
120
+ ( if propName = "href" then xss = true else xss = false )
110
121
)
111
122
or
112
123
// A redirection using the AngularJS `$location` service
113
124
exists ( AngularJS:: ServiceReference service |
114
125
service .getName ( ) = "$location" and
115
126
this .asExpr ( ) = service .getAMethodCall ( "url" ) .getArgument ( 0 )
116
- )
127
+ ) and
128
+ xss = false
117
129
}
130
+
131
+ override predicate isXSSSink ( ) { xss = true }
118
132
}
119
133
120
134
/**
@@ -164,6 +178,8 @@ module ClientSideUrlRedirect {
164
178
this = attr .getValueNode ( )
165
179
)
166
180
}
181
+
182
+ override predicate isXSSSink ( ) { any ( ) }
167
183
}
168
184
169
185
/**
@@ -177,6 +193,8 @@ module ClientSideUrlRedirect {
177
193
this = DataFlow:: valueNode ( pw .getRhs ( ) )
178
194
)
179
195
}
196
+
197
+ override predicate isXSSSink ( ) { any ( ) }
180
198
}
181
199
182
200
/**
@@ -193,6 +211,8 @@ module ClientSideUrlRedirect {
193
211
this = attr .getValue ( ) .flow ( )
194
212
)
195
213
}
214
+
215
+ override predicate isXSSSink ( ) { any ( ) }
196
216
}
197
217
198
218
/**
0 commit comments