@@ -20,57 +20,47 @@ import semmle.code.csharp.security.dataflow.SqlInjectionQuery as SqlInjection
20
20
import semmle.code.csharp.security.dataflow.flowsinks.Html
21
21
import semmle.code.csharp.security.dataflow.UrlRedirectQuery as UrlRedirect
22
22
import semmle.code.csharp.security.Sanitizers
23
- import semmle.code.csharp.dataflow.DataFlow2:: DataFlow2
24
- import semmle.code.csharp.dataflow.DataFlow2:: DataFlow2:: PathGraph
25
- import semmle.code.csharp.dataflow.TaintTracking2
23
+ import EncodingConfigurations:: Flow:: PathGraph
24
+
25
+ signature module EncodingConfigSig {
26
+ /** Holds if `n` is a node whose value must be encoded. */
27
+ predicate requiresEncoding ( DataFlow:: Node n ) ;
28
+
29
+ /** Holds if `e` is a possible valid encoded value. */
30
+ predicate isPossibleEncodedValue ( Expr e ) ;
31
+ }
26
32
27
33
/**
28
34
* A configuration for specifying expressions that must be
29
35
* encoded, along with a set of potential valid encoded values.
30
36
*/
31
- abstract class RequiresEncodingConfiguration extends TaintTracking2:: Configuration {
32
- bindingset [ this ]
33
- RequiresEncodingConfiguration ( ) { any ( ) }
34
-
35
- /** Gets a textual representation of this kind of encoding requirement. */
36
- abstract string getKind ( ) ;
37
-
38
- /** Holds if `e` is an expression whose value must be encoded. */
39
- abstract predicate requiresEncoding ( Node n ) ;
40
-
41
- /** Holds if `e` is a possible valid encoded value. */
42
- predicate isPossibleEncodedValue ( Expr e ) { none ( ) }
43
-
44
- /**
45
- * Holds if `encodedValue` is a possibly ill-encoded value that reaches
46
- * `sink`, where `sink` is an expression of kind `kind` that is required
47
- * to be encoded.
48
- */
49
- predicate hasWrongEncoding ( PathNode encodedValue , PathNode sink , string kind ) {
50
- this .hasFlowPath ( encodedValue , sink ) and
51
- kind = this .getKind ( )
52
- }
53
-
54
- override predicate isSource ( Node source ) {
37
+ module RequiresEncodingConfig< EncodingConfigSig EncodingConfig> implements DataFlow:: ConfigSig {
38
+ predicate isSource ( DataFlow:: Node source ) {
55
39
// all encoded values that do not match this configuration are
56
40
// considered sources
57
41
exists ( Expr e | e = source .asExpr ( ) |
58
42
e instanceof EncodedValue and
59
- not this . isPossibleEncodedValue ( e )
43
+ not EncodingConfig :: isPossibleEncodedValue ( e )
60
44
)
61
45
}
62
46
63
- override predicate isSink ( Node sink ) { this . requiresEncoding ( sink ) }
47
+ predicate isSink ( DataFlow :: Node sink ) { EncodingConfig :: requiresEncoding ( sink ) }
64
48
65
- override predicate isSanitizer ( Node sanitizer ) { this .isPossibleEncodedValue ( sanitizer .asExpr ( ) ) }
49
+ predicate isBarrier ( DataFlow:: Node sanitizer ) {
50
+ EncodingConfig:: isPossibleEncodedValue ( sanitizer .asExpr ( ) )
51
+ }
66
52
67
- override int fieldFlowBranchLimit ( ) { result = 0 }
53
+ int fieldFlowBranchLimit ( ) { result = 0 }
68
54
}
69
55
70
56
/** An encoded value, for example a call to `HttpServerUtility.HtmlEncode`. */
71
57
class EncodedValue extends Expr {
72
58
EncodedValue ( ) {
73
- any ( RequiresEncodingConfiguration c ) .isPossibleEncodedValue ( this )
59
+ EncodingConfigurations:: SqlExprEncodingConfig:: isPossibleEncodedValue ( this )
60
+ or
61
+ EncodingConfigurations:: HtmlExprEncodingConfig:: isPossibleEncodedValue ( this )
62
+ or
63
+ EncodingConfigurations:: UrlExprEncodingConfig:: isPossibleEncodedValue ( this )
74
64
or
75
65
this = any ( SystemWebHttpUtility c ) .getAJavaScriptStringEncodeMethod ( ) .getACall ( )
76
66
or
@@ -86,18 +76,20 @@ class EncodedValue extends Expr {
86
76
}
87
77
88
78
module EncodingConfigurations {
89
- /** An encoding configuration for SQL expressions. */
90
- class SqlExpr extends RequiresEncodingConfiguration {
91
- SqlExpr ( ) { this = "SqlExpr" }
79
+ module SqlExprEncodingConfig implements EncodingConfigSig {
80
+ predicate requiresEncoding ( DataFlow:: Node n ) { n instanceof SqlInjection:: Sink }
92
81
93
- override string getKind ( ) { result = "SQL expression" }
82
+ predicate isPossibleEncodedValue ( Expr e ) { none ( ) }
83
+ }
94
84
95
- override predicate requiresEncoding ( Node n ) { n instanceof SqlInjection:: Sink }
85
+ /** An encoding configuration for SQL expressions. */
86
+ module SqlExprConfig implements DataFlow:: ConfigSig {
87
+ import RequiresEncodingConfig< SqlExprEncodingConfig > as Super
96
88
97
89
// no override for `isPossibleEncodedValue` as SQL parameters should
98
90
// be used instead of explicit encoding
99
- override predicate isSource ( Node source ) {
100
- super . isSource ( source )
91
+ predicate isSource ( DataFlow :: Node source ) {
92
+ Super :: isSource ( source )
101
93
or
102
94
// consider quote-replacing calls as additional sources for
103
95
// SQL expressions (e.g., `s.Replace("\"", "\"\"")`)
@@ -107,32 +99,62 @@ module EncodingConfigurations {
107
99
mc .getArgument ( 0 ) .getValue ( ) .regexpMatch ( "\"|'|`" )
108
100
)
109
101
}
102
+
103
+ predicate isSink = Super:: isSink / 1 ;
104
+
105
+ predicate isBarrier = Super:: isBarrier / 1 ;
106
+
107
+ int fieldFlowBranchLimit ( ) { result = Super:: fieldFlowBranchLimit ( ) }
108
+ }
109
+
110
+ module SqlExpr = TaintTracking:: Global< SqlExprConfig > ;
111
+
112
+ module HtmlExprEncodingConfig implements EncodingConfigSig {
113
+ predicate requiresEncoding ( DataFlow:: Node n ) { n instanceof HtmlSink }
114
+
115
+ predicate isPossibleEncodedValue ( Expr e ) { e instanceof HtmlSanitizedExpr }
110
116
}
111
117
112
118
/** An encoding configuration for HTML expressions. */
113
- class HtmlExpr extends RequiresEncodingConfiguration {
114
- HtmlExpr ( ) { this = "HtmlExpr" }
119
+ module HtmlExprConfig = RequiresEncodingConfig< HtmlExprEncodingConfig > ;
115
120
116
- override string getKind ( ) { result = "HTML expression" }
121
+ module HtmlExpr = TaintTracking :: Global < HtmlExprConfig > ;
117
122
118
- override predicate requiresEncoding ( Node n ) { n instanceof HtmlSink }
123
+ module UrlExprEncodingConfig implements EncodingConfigSig {
124
+ predicate requiresEncoding ( DataFlow:: Node n ) { n instanceof UrlRedirect:: Sink }
119
125
120
- override predicate isPossibleEncodedValue ( Expr e ) { e instanceof HtmlSanitizedExpr }
126
+ predicate isPossibleEncodedValue ( Expr e ) { e instanceof UrlSanitizedExpr }
121
127
}
122
128
123
129
/** An encoding configuration for URL expressions. */
124
- class UrlExpr extends RequiresEncodingConfiguration {
125
- UrlExpr ( ) { this = "UrlExpr" }
130
+ module UrlExprConfig = RequiresEncodingConfig< UrlExprEncodingConfig > ;
126
131
127
- override string getKind ( ) { result = "URL expression" }
132
+ module UrlExpr = TaintTracking :: Global < UrlExprConfig > ;
128
133
129
- override predicate requiresEncoding ( Node n ) { n instanceof UrlRedirect:: Sink }
134
+ module Flow =
135
+ DataFlow:: MergePathGraph3< SqlExpr:: PathNode , HtmlExpr:: PathNode , UrlExpr:: PathNode ,
136
+ SqlExpr:: PathGraph , HtmlExpr:: PathGraph , UrlExpr:: PathGraph > ;
130
137
131
- override predicate isPossibleEncodedValue ( Expr e ) { e instanceof UrlSanitizedExpr }
138
+ /**
139
+ * Holds if `encodedValue` is a possibly ill-encoded value that reaches
140
+ * `sink`, where `sink` is an expression of kind `kind` that is required
141
+ * to be encoded.
142
+ */
143
+ predicate hasWrongEncoding ( Flow:: PathNode encodedValue , Flow:: PathNode sink , string kind ) {
144
+ SqlExpr:: flowPath ( encodedValue .asPathNode1 ( ) , sink .asPathNode1 ( ) ) and
145
+ kind = "SQL expression"
146
+ or
147
+ HtmlExpr:: flowPath ( encodedValue .asPathNode2 ( ) , sink .asPathNode2 ( ) ) and
148
+ kind = "HTML expression"
149
+ or
150
+ UrlExpr:: flowPath ( encodedValue .asPathNode3 ( ) , sink .asPathNode3 ( ) ) and
151
+ kind = "URL expression"
132
152
}
133
153
}
134
154
135
- from RequiresEncodingConfiguration c , PathNode encodedValue , PathNode sink , string kind
136
- where c .hasWrongEncoding ( encodedValue , sink , kind )
155
+ from
156
+ EncodingConfigurations:: Flow:: PathNode encodedValue , EncodingConfigurations:: Flow:: PathNode sink ,
157
+ string kind
158
+ where EncodingConfigurations:: hasWrongEncoding ( encodedValue , sink , kind )
137
159
select sink .getNode ( ) , encodedValue , sink , "This " + kind + " may include data from a $@." ,
138
160
encodedValue .getNode ( ) , "possibly inappropriately encoded value"
0 commit comments