@@ -15,7 +15,7 @@ import javascript
1515/** Gets a property name of `req` which refers to data usually derived from cookie data. */
1616string cookieProperty ( ) { result = "session" or result = "cookies" or result = "user" }
1717
18- /** Gets a data flow node that flows to the base of an access to `cookies`, `session`, or `user`. */
18+ /** Gets a data flow node that flows to the base of a reference to `cookies`, `session`, or `user`. */
1919private DataFlow:: SourceNode nodeLeadingToCookieAccess ( DataFlow:: TypeBackTracker t ) {
2020 t .start ( ) and
2121 exists ( DataFlow:: PropRef value |
@@ -97,11 +97,72 @@ DataFlow::CallNode csrfMiddlewareCreation() {
9797 )
9898}
9999
100+ /**
101+ * Gets a data flow node that flows to the base of a write to `cookies`, `session`, or `user`,
102+ * where the written property has `csrf` or `xsrf` in its name.
103+ */
104+ private DataFlow:: SourceNode nodeLeadingToCsrfWrite ( DataFlow:: TypeBackTracker t ) {
105+ t .start ( ) and
106+ exists ( DataFlow:: PropRef value |
107+ value = result .getAPropertyRead ( cookieProperty ( ) ) .getAPropertyWrite ( ) and
108+ value .getPropertyName ( ) .regexpMatch ( "(?i).*(csrf|xsrf).*" )
109+ )
110+ or
111+ exists ( DataFlow:: TypeBackTracker t2 | result = nodeLeadingToCsrfWrite ( t2 ) .backtrack ( t2 , t ) )
112+ }
113+
114+ /**
115+ * Gets a route handler that sets an CSRF related cookie.
116+ */
117+ private Express:: RouteHandler getAHandlerSettingCsrfCookie ( ) {
118+ exists ( HTTP:: CookieDefinition setCookie |
119+ setCookie .getNameArgument ( ) .getStringValue ( ) .regexpMatch ( "(?i).*(csrf|xsrf).*" ) and
120+ result = setCookie .getRouteHandler ( )
121+ )
122+ }
123+
124+ /**
125+ * Holds if `handler` is protecting from CSRF.
126+ * This is indicated either by the request parameter having a CSRF related write to a session variable.
127+ * Or by the response parameter setting a CSRF related cookie.
128+ */
129+ predicate isACsrfProtectionRouteHandler ( Express:: RouteHandler handler ) {
130+ DataFlow:: parameterNode ( handler .getRequestParameter ( ) ) =
131+ nodeLeadingToCsrfWrite ( DataFlow:: TypeBackTracker:: end ( ) )
132+ or
133+ handler = getAHandlerSettingCsrfCookie ( )
134+ }
135+
136+ /** Gets a data flow node refering to a route handler that is protecting against CSRF. */
137+ private DataFlow:: SourceNode getACsrfProtectionRouteHandler ( DataFlow:: TypeTracker t ) {
138+ t .start ( ) and
139+ isACsrfProtectionRouteHandler ( result )
140+ or
141+ exists ( DataFlow:: TypeTracker t2 , DataFlow:: SourceNode pred |
142+ pred = getACsrfProtectionRouteHandler ( t2 )
143+ |
144+ result = pred .track ( t2 , t )
145+ or
146+ t = t2 and
147+ HTTP:: routeHandlerStep ( pred , result )
148+ )
149+ }
150+
151+ /**
152+ * Gets an express route handler expression that is either a custom CSRF protection middleware,
153+ * or a CSFR protecting library.
154+ */
155+ Express:: RouteHandlerExpr getACsrfMiddleware ( ) {
156+ csrfMiddlewareCreation ( ) .flowsToExpr ( result )
157+ or
158+ getACsrfProtectionRouteHandler ( DataFlow:: TypeTracker:: end ( ) ) .flowsToExpr ( result )
159+ }
160+
100161/**
101162 * Holds if the given route handler is protected by CSRF middleware.
102163 */
103164predicate hasCsrfMiddleware ( Express:: RouteHandlerExpr handler ) {
104- csrfMiddlewareCreation ( ) . flowsToExpr ( handler .getAMatchingAncestor ( ) )
165+ getACsrfMiddleware ( ) = handler .getAMatchingAncestor ( )
105166}
106167
107168from
0 commit comments