@@ -7,65 +7,61 @@ import javascript
7
7
private import semmle.javascript.security.TaintedUrlSuffix
8
8
import DomBasedXssCustomizations:: DomBasedXss
9
9
10
- /**
11
- * DEPRECATED. Use `HtmlInjectionConfiguration` or `JQueryHtmlOrSelectorInjectionConfiguration`.
12
- */
13
- deprecated class Configuration = HtmlInjectionConfiguration ;
14
-
15
10
/**
16
11
* DEPRECATED. Use `Vue::VHtmlSourceWrite` instead.
17
12
*/
18
13
deprecated class VHtmlSourceWrite = Vue:: VHtmlSourceWrite ;
19
14
20
- /**
21
- * A taint-tracking configuration for reasoning about XSS.
22
- */
23
- class HtmlInjectionConfiguration extends TaintTracking:: Configuration {
24
- HtmlInjectionConfiguration ( ) { this = "HtmlInjection" }
25
-
26
- override predicate isSource ( DataFlow:: Node source ) { source instanceof Source }
27
-
28
- override predicate isSink ( DataFlow:: Node sink ) {
29
- sink instanceof Sink and
30
- not sink instanceof JQueryHtmlOrSelectorSink // Handled by JQueryHtmlOrSelectorInjectionConfiguration below
31
- }
15
+ /** DEPRECATED. Use `Configuration`. */
16
+ deprecated class HtmlInjectionConfiguration = Configuration ;
32
17
33
- override predicate isSanitizer ( DataFlow:: Node node ) {
34
- super .isSanitizer ( node )
35
- or
36
- node instanceof Sanitizer
37
- }
38
-
39
- override predicate isSanitizerGuard ( TaintTracking:: SanitizerGuardNode guard ) {
40
- guard instanceof SanitizerGuard
41
- }
18
+ /** DEPRECATED. Use `Configuration`. */
19
+ deprecated class JQueryHtmlOrSelectorInjectionConfiguration = Configuration ;
42
20
43
- override predicate isSanitizerEdge ( DataFlow:: Node pred , DataFlow:: Node succ ) {
44
- isOptionallySanitizedEdge ( pred , succ )
21
+ /**
22
+ * A sink that is not a URL write or a JQuery selector,
23
+ * assumed to be a value that is interpreted as HTML.
24
+ */
25
+ class HTMLSink extends DataFlow:: Node instanceof Sink {
26
+ HTMLSink ( ) {
27
+ not this instanceof WriteURLSink and
28
+ not this instanceof JQueryHtmlOrSelectorSink
45
29
}
46
30
}
47
31
48
32
/**
49
- * A taint-tracking configuration for reasoning about injection into the jQuery `$` function
50
- * or similar, where the interpretation of the input string depends on its first character.
33
+ * A taint-tracking configuration for reasoning about XSS.
34
+ * Both ordinary HTML sinks, URL sinks, and JQuery selector based sinks.
35
+ * - HTML sinks are sinks for any tainted value
36
+ * - URL sinks are only sinks when the scheme is user controlled
37
+ * - JQuery selector sinks are sinks when the tainted value can start with `<`.
51
38
*
52
- * Values are only considered tainted if they can start with the `<` character.
39
+ * The above is achieved using three flow labels:
40
+ * - TaintedUrlSuffix: a URL where the attacker only controls a suffix.
41
+ * - Taint: a tainted value where the attacker controls part of the value.
42
+ * - PrefixLabel: a tainted value where the attacker controls the prefix
53
43
*/
54
- class JQueryHtmlOrSelectorInjectionConfiguration extends TaintTracking:: Configuration {
55
- JQueryHtmlOrSelectorInjectionConfiguration ( ) { this = "JQueryHtmlOrSelectorInjection " }
44
+ class Configuration extends TaintTracking:: Configuration {
45
+ Configuration ( ) { this = "HtmlInjection " }
56
46
57
47
override predicate isSource ( DataFlow:: Node source , DataFlow:: FlowLabel label ) {
58
- // Reuse any source not derived from location
59
48
source instanceof Source and
60
- not source = [ DOM :: locationRef ( ) , DOM :: locationRef ( ) . getAPropertyRead ( ) ] and
61
- label . isTaint ( )
49
+ ( label . isTaint ( ) or label = prefixLabel ( ) ) and
50
+ not source = TaintedUrlSuffix :: source ( )
62
51
or
63
- source = [ DOM :: locationSource ( ) , DOM :: locationRef ( ) . getAPropertyRead ( [ "hash" , "search" ] ) ] and
52
+ source = TaintedUrlSuffix :: source ( ) and
64
53
label = TaintedUrlSuffix:: label ( )
65
54
}
66
55
67
56
override predicate isSink ( DataFlow:: Node sink , DataFlow:: FlowLabel label ) {
68
- sink instanceof JQueryHtmlOrSelectorSink and label .isTaint ( )
57
+ sink instanceof HTMLSink and
58
+ label = [ TaintedUrlSuffix:: label ( ) , prefixLabel ( ) , DataFlow:: FlowLabel:: taint ( ) ]
59
+ or
60
+ sink instanceof JQueryHtmlOrSelectorSink and
61
+ label = [ DataFlow:: FlowLabel:: taint ( ) , prefixLabel ( ) ]
62
+ or
63
+ sink instanceof WriteURLSink and
64
+ label = prefixLabel ( )
69
65
}
70
66
71
67
override predicate isSanitizer ( DataFlow:: Node node ) {
@@ -78,6 +74,32 @@ class JQueryHtmlOrSelectorInjectionConfiguration extends TaintTracking::Configur
78
74
guard instanceof SanitizerGuard
79
75
}
80
76
77
+ override predicate isLabeledBarrier ( DataFlow:: Node node , DataFlow:: FlowLabel lbl ) {
78
+ super .isLabeledBarrier ( node , lbl )
79
+ or
80
+ // copy all taint barriers to the TaintedUrlSuffix/PrefixLabel label. This copies both the ordinary sanitizers and the sanitizer-guards.
81
+ super .isLabeledBarrier ( node , DataFlow:: FlowLabel:: taint ( ) ) and
82
+ lbl = [ TaintedUrlSuffix:: label ( ) , prefixLabel ( ) ]
83
+ or
84
+ // any non-first string-concatenation leaf is a barrier for the prefix label.
85
+ exists ( StringOps:: ConcatenationRoot root |
86
+ node = root .getALeaf ( ) and
87
+ not node = root .getFirstLeaf ( ) and
88
+ lbl = prefixLabel ( )
89
+ )
90
+ or
91
+ // we assume that `.join()` calls have a prefix, and thus block the prefix label.
92
+ node = any ( DataFlow:: MethodCallNode call | call .getMethodName ( ) = "join" ) and
93
+ lbl = prefixLabel ( )
94
+ }
95
+
96
+ override predicate isSanitizerEdge (
97
+ DataFlow:: Node pred , DataFlow:: Node succ , DataFlow:: FlowLabel label
98
+ ) {
99
+ isOptionallySanitizedEdge ( pred , succ ) and
100
+ label = [ DataFlow:: FlowLabel:: taint ( ) , prefixLabel ( ) , TaintedUrlSuffix:: label ( ) ]
101
+ }
102
+
81
103
override predicate isAdditionalFlowStep (
82
104
DataFlow:: Node src , DataFlow:: Node trg , DataFlow:: FlowLabel inlbl , DataFlow:: FlowLabel outlbl
83
105
) {
@@ -89,5 +111,15 @@ class JQueryHtmlOrSelectorInjectionConfiguration extends TaintTracking::Configur
89
111
inlbl = TaintedUrlSuffix:: label ( ) and
90
112
outlbl .isTaint ( )
91
113
)
114
+ or
115
+ // inherit all ordinary taint steps for prefixLabel
116
+ inlbl = prefixLabel ( ) and
117
+ outlbl = prefixLabel ( ) and
118
+ TaintTracking:: sharedTaintStep ( src , trg )
119
+ or
120
+ // steps out of taintedSuffixlabel to taint-label are also a steps to prefixLabel.
121
+ TaintedUrlSuffix:: step ( src , trg , TaintedUrlSuffix:: label ( ) , DataFlow:: FlowLabel:: taint ( ) ) and
122
+ inlbl = TaintedUrlSuffix:: label ( ) and
123
+ outlbl = prefixLabel ( )
92
124
}
93
125
}
0 commit comments