@@ -17,91 +17,103 @@ import csharp
1717import semmle.code.asp.WebConfig
1818import semmle.code.csharp.frameworks.system.Web
1919import semmle.code.csharp.frameworks.microsoft.AspNetCore
20- deprecated import experimental.dataflow.flowsources.AuthCookie
20+ import experimental.dataflow.flowsources.AuthCookie
2121
22- deprecated query predicate problems ( Expr httpOnlySink , string message ) {
22+ predicate cookieAppendHttpOnlyByDefault ( ) {
23+ // default is set to `Always`
24+ getAValueForCookiePolicyProp ( "HttpOnly" ) .getValue ( ) = "1"
25+ or
26+ // there is an `OnAppendCookie` callback that sets `HttpOnly` to true
27+ not OnAppendCookieHttpOnlyTracking:: flowTo ( _)
28+ }
29+
30+ predicate httpOnlyFalse ( ObjectCreation oc ) {
31+ exists ( Assignment a |
32+ getAValueForProp ( oc , a , "HttpOnly" ) = a .getRValue ( ) and
33+ a .getRValue ( ) .getValue ( ) = "false"
34+ )
35+ }
36+
37+ predicate httpOnlyFalseOrNotSet ( ObjectCreation oc ) {
38+ httpOnlyFalse ( oc )
39+ or
40+ not isPropertySet ( oc , "HttpOnly" )
41+ }
42+
43+ predicate nonHttpOnlyCookieOptionsCreation ( ObjectCreation oc , MethodCall append ) {
44+ // `HttpOnly` property in `CookieOptions` passed to IResponseCookies.Append(...) wasn't set
45+ oc .getType ( ) instanceof MicrosoftAspNetCoreHttpCookieOptions and
46+ httpOnlyFalseOrNotSet ( oc ) and
47+ exists ( DataFlow:: Node creation , DataFlow:: Node sink |
48+ CookieOptionsTracking:: flow ( creation , sink ) and
49+ creation .asExpr ( ) = oc and
50+ sink .asExpr ( ) = append .getArgument ( 2 )
51+ )
52+ }
53+
54+ predicate nonHttpOnlySensitiveCookieCreation ( ObjectCreation oc ) {
55+ oc .getType ( ) instanceof SystemWebHttpCookie and
56+ isCookieWithSensitiveName ( oc .getArgument ( 0 ) ) and
2357 (
24- exists ( Assignment a , Expr val |
25- httpOnlySink = a .getRValue ( ) and
26- val .getValue ( ) = "false" and
27- (
28- exists ( ObjectCreation oc |
29- getAValueForProp ( oc , a , "HttpOnly" ) = val and
30- (
31- oc .getType ( ) instanceof SystemWebHttpCookie and
32- isCookieWithSensitiveName ( oc .getArgument ( 0 ) )
33- or
34- exists ( MethodCall mc , MicrosoftAspNetCoreHttpResponseCookies iResponse |
35- oc .getType ( ) instanceof MicrosoftAspNetCoreHttpCookieOptions and
36- iResponse .getAppendMethod ( ) = mc .getTarget ( ) and
37- isCookieWithSensitiveName ( mc .getArgument ( 0 ) ) and
38- // there is no callback `OnAppendCookie` that sets `HttpOnly` to true
39- not OnAppendCookieHttpOnlyTracking:: flowTo ( _) and
40- // Passed as third argument to `IResponseCookies.Append`
41- exists ( DataFlow:: Node creation , DataFlow:: Node append |
42- CookieOptionsTracking:: flow ( creation , append ) and
43- creation .asExpr ( ) = oc and
44- append .asExpr ( ) = mc .getArgument ( 2 )
45- )
46- )
47- )
48- )
49- or
50- exists ( PropertyWrite pw |
51- (
52- pw .getProperty ( ) .getDeclaringType ( ) instanceof MicrosoftAspNetCoreHttpCookieBuilder or
53- pw .getProperty ( ) .getDeclaringType ( ) instanceof
54- MicrosoftAspNetCoreAuthenticationCookiesCookieAuthenticationOptions
55- ) and
56- pw .getProperty ( ) .getName ( ) = "HttpOnly" and
57- a .getLValue ( ) = pw and
58- DataFlow:: localExprFlow ( val , a .getRValue ( ) )
59- )
60- )
61- )
58+ httpOnlyFalse ( oc )
6259 or
63- exists ( Call c |
64- httpOnlySink = c and
60+ // the property wasn't explicitly set, so a default value from config is used
61+ not isPropertySet ( oc , "HttpOnly" ) and
62+ // the default in config is not set to `true`
63+ not exists ( XmlElement element |
64+ element instanceof HttpCookiesElement and
65+ element .( HttpCookiesElement ) .isHttpOnlyCookies ( )
66+ )
67+ )
68+ }
69+
70+ predicate sensitiveCookieAppend ( MethodCall mc ) {
71+ exists ( MicrosoftAspNetCoreHttpResponseCookies iResponse |
72+ iResponse .getAppendMethod ( ) = mc .getTarget ( ) and
73+ isCookieWithSensitiveName ( mc .getArgument ( 0 ) )
74+ )
75+ }
76+
77+ predicate nonHttpOnlyCookieCall ( Call c ) {
78+ (
79+ not cookieAppendHttpOnlyByDefault ( ) and
80+ exists ( MethodCall mc |
81+ sensitiveCookieAppend ( mc ) and
6582 (
66- exists ( MicrosoftAspNetCoreHttpResponseCookies iResponse , MethodCall mc |
67- // default is not configured or is not set to `Always`
68- not getAValueForCookiePolicyProp ( "HttpOnly" ) .getValue ( ) = "1" and
69- // there is no callback `OnAppendCookie` that sets `HttpOnly` to true
70- not OnAppendCookieHttpOnlyTracking:: flowTo ( _) and
71- iResponse .getAppendMethod ( ) = mc .getTarget ( ) and
72- isCookieWithSensitiveName ( mc .getArgument ( 0 ) ) and
73- (
74- // `HttpOnly` property in `CookieOptions` passed to IResponseCookies.Append(...) wasn't set
75- exists ( ObjectCreation oc |
76- oc = c and
77- oc .getType ( ) instanceof MicrosoftAspNetCoreHttpCookieOptions and
78- not isPropertySet ( oc , "HttpOnly" ) and
79- exists ( DataFlow:: Node creation |
80- CookieOptionsTracking:: flow ( creation , _) and
81- creation .asExpr ( ) = oc
82- )
83- )
84- or
85- // IResponseCookies.Append(String, String) was called, `HttpOnly` is set to `false` by default
86- mc = c and
87- mc .getNumberOfArguments ( ) < 3
88- )
89- )
83+ nonHttpOnlyCookieOptionsCreation ( c , mc )
9084 or
91- exists ( ObjectCreation oc |
92- oc = c and
93- oc .getType ( ) instanceof SystemWebHttpCookie and
94- isCookieWithSensitiveName ( oc .getArgument ( 0 ) ) and
95- // the property wasn't explicitly set, so a default value from config is used
96- not isPropertySet ( oc , "HttpOnly" ) and
97- // the default in config is not set to `true`
98- not exists ( XmlElement element |
99- element instanceof HttpCookiesElement and
100- element .( HttpCookiesElement ) .isHttpOnlyCookies ( )
101- )
102- )
85+ // IResponseCookies.Append(String, String) was called, `HttpOnly` is set to `false` by default
86+ mc = c and
87+ mc .getNumberOfArguments ( ) < 3
10388 )
10489 )
105- ) and
106- message = "Cookie attribute 'HttpOnly' is not set to true."
90+ or
91+ nonHttpOnlySensitiveCookieCreation ( c )
92+ )
10793}
94+
95+ predicate nonHttpOnlyPolicyAssignment ( Assignment a , Expr val ) {
96+ val .getValue ( ) = "false" and
97+ exists ( PropertyWrite pw |
98+ (
99+ pw .getProperty ( ) .getDeclaringType ( ) instanceof MicrosoftAspNetCoreHttpCookieBuilder or
100+ pw .getProperty ( ) .getDeclaringType ( ) instanceof
101+ MicrosoftAspNetCoreAuthenticationCookiesCookieAuthenticationOptions
102+ ) and
103+ pw .getProperty ( ) .getName ( ) = "HttpOnly" and
104+ a .getLValue ( ) = pw and
105+ DataFlow:: localExprFlow ( val , a .getRValue ( ) )
106+ )
107+ }
108+
109+ from Expr httpOnlySink
110+ where
111+ (
112+ nonHttpOnlyCookieCall ( httpOnlySink )
113+ or
114+ exists ( Assignment a |
115+ httpOnlySink = a .getRValue ( ) and
116+ nonHttpOnlyPolicyAssignment ( a , _)
117+ )
118+ )
119+ select httpOnlySink , "Cookie attribute 'HttpOnly' is not set to true."
0 commit comments