@@ -23,6 +23,14 @@ module ClientSideUrlRedirect {
2323 */
2424 abstract class Sanitizer extends DataFlow:: Node { }
2525
26+ /**
27+ * A flow label for values that represent the URL of the current document, and
28+ * hence are only partially user-controlled.
29+ */
30+ class DocumentUrl extends DataFlow:: FlowLabel {
31+ DocumentUrl ( ) { this = "document.url" }
32+ }
33+
2634 /**
2735 * A taint-tracking configuration for reasoning about unvalidated URL redirections.
2836 */
@@ -35,24 +43,37 @@ module ClientSideUrlRedirect {
3543 source instanceof Source
3644 }
3745
46+ override predicate isSource ( DataFlow:: Node source , DataFlow:: FlowLabel lbl ) {
47+ source instanceof RemoteFlowSource and
48+ lbl = DataFlow:: FlowLabel:: taint ( )
49+ or
50+ isDocumentURL ( source .asExpr ( ) ) and
51+ lbl instanceof DocumentUrl
52+ }
53+
3854 override predicate isSink ( DataFlow:: Node sink ) {
3955 sink instanceof Sink
4056 }
4157
58+ override predicate isSink ( DataFlow:: Node sink , DataFlow:: FlowLabel f ) {
59+ sink instanceof UrlSink and
60+ f = DataFlow:: FlowLabel:: taint ( )
61+ }
62+
4263 override predicate isSanitizer ( DataFlow:: Node node ) {
4364 super .isSanitizer ( node ) or
44- isSafeLocationProperty ( node .asExpr ( ) ) or
4565 node instanceof Sanitizer
4666 }
4767
4868 override predicate isSanitizer ( DataFlow:: Node source , DataFlow:: Node sink ) {
4969 sanitizingPrefixEdge ( source , sink )
5070 }
51- }
5271
53- /** A source of remote user input, considered as a flow source for unvalidated URL redirects. */
54- class RemoteFlowSourceAsSource extends Source {
55- RemoteFlowSourceAsSource ( ) { this instanceof RemoteFlowSource }
72+ override predicate isAdditionalFlowStep ( DataFlow:: Node pred , DataFlow:: Node succ , DataFlow:: FlowLabel f , DataFlow:: FlowLabel g ) {
73+ queryAccess ( pred , succ ) and
74+ f instanceof DocumentUrl and
75+ g = DataFlow:: FlowLabel:: taint ( )
76+ }
5677 }
5778
5879 /**
@@ -84,39 +105,13 @@ module ClientSideUrlRedirect {
84105 )
85106 }
86107
87- /**
88- * A taint tracking configuration for identifying accesses of the query string of the current URL.
89- */
90- private class LocationHrefDataFlowConfiguration extends TaintTracking:: Configuration {
91- LocationHrefDataFlowConfiguration ( ) {
92- this = "LocationHrefDataFlowConfiguration"
93- }
94-
95- override predicate isSource ( DataFlow:: Node source ) {
96- isDocumentURL ( source .asExpr ( ) )
97- }
98-
99- override predicate isSink ( DataFlow:: Node sink ) {
100- queryAccess ( sink , _)
101- }
102- }
103-
104- /**
105- * An access of the query string of the current URL.
106- */
107- class LocationSearchSource extends Source {
108- LocationSearchSource ( ) {
109- exists ( LocationHrefDataFlowConfiguration cfg , DataFlow:: Node nd |
110- cfg .hasFlow ( _, nd ) and
111- queryAccess ( nd , this )
112- )
113- }
108+ abstract class UrlSink extends DataFlow:: Node {
114109 }
115110
116111 /**
117112 * A sink which is used to set the window location.
118113 */
119- class LocationSink extends Sink , DataFlow:: ValueNode {
114+ class LocationSink extends UrlSink , DataFlow:: ValueNode {
120115 LocationSink ( ) {
121116 // A call to a `window.navigate` or `window.open`
122117 exists ( string name |
@@ -157,7 +152,7 @@ module ClientSideUrlRedirect {
157152 /**
158153 * An expression that may be interpreted as the URL of a script.
159154 */
160- abstract class ScriptUrlSink extends Sink {
155+ abstract class ScriptUrlSink extends UrlSink {
161156 }
162157
163158 /**
0 commit comments