@@ -56,15 +56,47 @@ module CodeInjection {
56
56
*/
57
57
class TemplateTagInScriptSink extends Sink {
58
58
TemplateTagInScriptSink ( ) {
59
- // Note: currently viewing all tags in code as sinks, but this can lead to
60
- // some FPs when values are escaped correctly.
61
59
exists ( Templating:: TemplatePlaceholderTag tag |
62
- tag .isInCodeContext ( ) and
63
- this = tag .asDataFlowNode ( )
60
+ this = tag .asDataFlowNode ( ) and
61
+ tag .isEscapingInterpolation ( ) // to avoid double reporting, raw interpolation is only flagged by the XSS query
62
+ |
63
+ // In an attribute, HTML entities are expanded prior to JS parsing, so the escaping performed by the
64
+ // templating engine has no effect against code injection.
65
+ tag .isInCodeAttribute ( )
66
+ or
67
+ // In a script tag, HTML entities are not expanded.
68
+ // To reduce noise, we filter out a common pattern where a template tag occurs in a string literal,
69
+ // since HTML escaping prevents breaking out of the string literal.
70
+ //
71
+ // var foo = "<%= foo %>";
72
+ //
73
+ // However, we still flag the special case where multiple such strings occur on the same line, as injection can sometimes
74
+ // we obtained by injecting a backslash character at the end of the first one:
75
+ //
76
+ // init("<%= foo %">, "<%= bar %>");
77
+ //
78
+ // For example, setting foo to `\` and bar to `, alert(1));//`, code injection is obtained.
79
+ tag .isInScriptTag ( ) and
80
+ not tag .getEnclosingExpr ( ) = getLastStringWithPlaceholderOnLine ( tag .getLocation ( ) .getFile ( ) , tag .getLocation ( ) .getStartLine ( ) )
64
81
)
65
82
}
66
83
}
67
84
85
+ /** Gets the last string literal containing a template placeholder on the given line. */
86
+ pragma [ nomagic]
87
+ private StringLiteral getLastStringWithPlaceholderOnLine ( File file , int line ) {
88
+ result = max ( StringLiteral lit , Location loc |
89
+ loc = lit .getLocation ( ) and
90
+ loc .getFile ( ) = file and
91
+ loc .getStartLine ( ) = line and
92
+ lit = any ( Templating:: TemplatePlaceholderTag tag | tag .isEscapingInterpolation ( ) ) .getEnclosingExpr ( )
93
+ |
94
+ lit
95
+ order by
96
+ loc .getStartColumn ( )
97
+ )
98
+ }
99
+
68
100
/**
69
101
* A server-side template tag occurring in the context of another template language.
70
102
*/
0 commit comments