@@ -45,31 +45,31 @@ module Cookie {
45
45
* Holds if the cookie is authentication sensitive and lacks HttpOnly.
46
46
*/
47
47
abstract predicate isAuthNotHttpOnly ( ) ;
48
+ }
48
49
49
- /**
50
- * Holds if the expression is a variable with a sensitive name.
51
- */
52
- predicate isAuthVariable ( DataFlow:: Node expr ) {
53
- exists ( string val |
54
- (
55
- val = expr .getStringValue ( ) or
56
- val = expr .asExpr ( ) .( VarAccess ) .getName ( ) or
57
- val = expr .( DataFlow:: PropRead ) .getPropertyName ( )
58
- ) and
59
- regexpMatchAuth ( val )
60
- )
61
- or
62
- isAuthVariable ( expr .getAPredecessor ( ) )
63
- }
50
+ /**
51
+ * Holds if the expression is a variable with a sensitive name.
52
+ */
53
+ private predicate isAuthVariable ( DataFlow:: Node expr ) {
54
+ exists ( string val |
55
+ (
56
+ val = expr .getStringValue ( ) or
57
+ val = expr .asExpr ( ) .( VarAccess ) .getName ( ) or
58
+ val = expr .( DataFlow:: PropRead ) .getPropertyName ( )
59
+ ) and
60
+ regexpMatchAuth ( val )
61
+ )
62
+ or
63
+ isAuthVariable ( expr .getAPredecessor ( ) )
64
+ }
64
65
65
- /**
66
- * Holds if the string contains sensitive auth keyword, but not antiforgery token.
67
- */
68
- bindingset [ val]
69
- predicate regexpMatchAuth ( string val ) {
70
- val .regexpMatch ( "(?i).*(session|login|token|user|auth|credential).*" ) and
71
- not val .regexpMatch ( "(?i).*(xsrf|csrf|forgery).*" )
72
- }
66
+ /**
67
+ * Holds if the string contains sensitive auth keyword, but not antiforgery token.
68
+ */
69
+ bindingset [ val]
70
+ private predicate regexpMatchAuth ( string val ) {
71
+ val .regexpMatch ( "(?i).*(session|login|token|user|auth|credential).*" ) and
72
+ not val .regexpMatch ( "(?i).*(xsrf|csrf|forgery).*" )
73
73
}
74
74
75
75
/**
@@ -168,6 +168,26 @@ module Cookie {
168
168
}
169
169
}
170
170
171
+ private class AttributeToSetCookieHeaderTrackingConfig extends TaintTracking:: Configuration {
172
+ AttributeToSetCookieHeaderTrackingConfig ( ) { this = "AttributeToSetCookieHeaderTrackingConfig" }
173
+
174
+ override predicate isSource ( DataFlow:: Node source ) {
175
+ exists ( string s | source .mayHaveStringValue ( s ) )
176
+ }
177
+
178
+ override predicate isSink ( DataFlow:: Node sink ) { sink .asExpr ( ) instanceof TemplateLiteral }
179
+ }
180
+
181
+ private class SensitiveNameToSetCookieHeaderTrackingConfig extends TaintTracking:: Configuration {
182
+ SensitiveNameToSetCookieHeaderTrackingConfig ( ) {
183
+ this = "SensitiveNameToSetCookieHeaderTrackingConfig"
184
+ }
185
+
186
+ override predicate isSource ( DataFlow:: Node source ) { isAuthVariable ( source ) }
187
+
188
+ override predicate isSink ( DataFlow:: Node sink ) { sink .asExpr ( ) instanceof TemplateLiteral }
189
+ }
190
+
171
191
/**
172
192
* A cookie set using `Set-Cookie` header of an `HTTP` response.
173
193
* (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie).
@@ -197,7 +217,7 @@ module Cookie {
197
217
* A cookie is httpOnly if the `httpOnly` flag is specified in the cookie definition.
198
218
* The default is `false`.
199
219
*/
200
- override predicate isHttpOnly ( ) { allHaveCookieAttribute ( "httponly" ) }
220
+ override predicate isHttpOnly ( ) { allHaveCookieAttribute ( httpOnlyFlag ( ) ) }
201
221
202
222
/**
203
223
* The predicate holds only if all elements have the specified attribute.
@@ -209,6 +229,14 @@ module Cookie {
209
229
n .mayHaveStringValue ( s ) and
210
230
hasCookieAttribute ( s , attribute )
211
231
)
232
+ or
233
+ exists ( AttributeToSetCookieHeaderTrackingConfig cfg , DataFlow:: Node source |
234
+ cfg .hasFlow ( source , n ) and
235
+ exists ( string attr |
236
+ source .mayHaveStringValue ( attr ) and
237
+ attr .regexpMatch ( "(?i).*\\b" + attribute + "\\b.*" )
238
+ )
239
+ )
212
240
)
213
241
}
214
242
@@ -221,10 +249,19 @@ module Cookie {
221
249
exists ( string s |
222
250
n .mayHaveStringValue ( s ) and
223
251
(
224
- not hasCookieAttribute ( s , "httponly" ) and
252
+ not hasCookieAttribute ( s , httpOnlyFlag ( ) ) and
225
253
regexpMatchAuth ( getCookieName ( s ) )
226
254
)
227
255
)
256
+ or
257
+ not exists ( AttributeToSetCookieHeaderTrackingConfig cfg , DataFlow:: Node source |
258
+ cfg .hasFlow ( source , n ) and
259
+ exists ( string attr |
260
+ source .mayHaveStringValue ( attr ) and
261
+ attr .regexpMatch ( "(?i).*\\b" + httpOnlyFlag ( ) + "\\b.*" )
262
+ )
263
+ ) and
264
+ exists ( SensitiveNameToSetCookieHeaderTrackingConfig cfg | cfg .hasFlow ( _, n ) )
228
265
)
229
266
}
230
267
0 commit comments