@@ -69,22 +69,45 @@ module UntrustedToAllowOriginHeaderConfig implements DataFlow::ConfigSig {
6969 predicate isSink ( DataFlow:: Node sink ) { isSinkHW ( sink , _) }
7070}
7171
72+ module UntrustedToAllowOriginConfigConfig implements DataFlow:: ConfigSig {
73+ predicate isSource ( DataFlow:: Node source ) { source instanceof UntrustedFlowSource }
74+
75+ additional predicate isSinkWrite ( DataFlow:: Node sink , GinCors:: AllowOriginsWrite w ) {
76+ sink = w
77+ }
78+
79+ predicate isSink ( DataFlow:: Node sink ) { isSinkWrite ( sink , _) }
80+ }
81+
7282/**
7383 * Tracks taint flowfor reasoning about when an `UntrustedFlowSource` flows to
7484 * a `HeaderWrite` that writes an `Access-Control-Allow-Origin` header's value.
7585 */
7686module UntrustedToAllowOriginHeaderFlow = TaintTracking:: Global< UntrustedToAllowOriginHeaderConfig > ;
7787
88+ module UntrustedToAllowOriginConfigFlow = TaintTracking:: Global< UntrustedToAllowOriginConfigConfig > ;
89+
7890/**
7991 * Holds if the provided `allowOriginHW` HeaderWrite's parent ResponseWriter
8092 * also has another HeaderWrite that sets a `Access-Control-Allow-Credentials`
8193 * header to `true`.
8294 */
83- predicate allowCredentialsIsSetToTrue ( AllowOriginHeaderWrite allowOriginHW ) {
95+ predicate allowCredentialsIsSetToTrue ( DataFlow :: ExprNode allowOrigin ) {
8496 exists ( AllowCredentialsHeaderWrite allowCredentialsHW |
8597 allowCredentialsHW .getHeaderValue ( ) .toLowerCase ( ) = "true"
8698 |
87- allowOriginHW .getResponseWriter ( ) = allowCredentialsHW .getResponseWriter ( )
99+ allowOrigin .( AllowOriginHeaderWrite ) .getResponseWriter ( ) = allowCredentialsHW .getResponseWriter ( )
100+ )
101+ or
102+ exists ( GinCors:: AllowCredentialsWrite allowCredentialsGin |
103+ allowCredentialsGin .toString ( ) = "true"
104+ |
105+ //flow only goes in one direction so fix this before PR
106+ allowCredentialsGin .getConfig ( ) = allowOrigin .( GinCors:: AllowOriginsWrite ) .getConfig ( )
107+ and
108+ not exists ( GinCors:: AllowAllOriginsWrite allowAllOrigins |
109+ allowAllOrigins .toString ( ) = "true" //and DataFlow::localFlow(allowCredentialsGin.getBase(), allowAllOrigins.getBase())
110+ )
88111 )
89112}
90113
@@ -93,10 +116,12 @@ predicate allowCredentialsIsSetToTrue(AllowOriginHeaderWrite allowOriginHW) {
93116 * UntrustedFlowSource.
94117 * The `message` parameter is populated with the warning message to be returned by the query.
95118 */
96- predicate flowsFromUntrustedToAllowOrigin ( AllowOriginHeaderWrite allowOriginHW , string message ) {
119+ predicate flowsFromUntrustedToAllowOrigin ( DataFlow :: ExprNode allowOriginHW , string message ) {
97120 exists ( DataFlow:: Node sink |
98121 UntrustedToAllowOriginHeaderFlow:: flowTo ( sink ) and
99- UntrustedToAllowOriginHeaderConfig:: isSinkHW ( sink , allowOriginHW )
122+ UntrustedToAllowOriginHeaderConfig:: isSinkHW ( sink , allowOriginHW ) or
123+ UntrustedToAllowOriginConfigFlow:: flowTo ( sink ) and
124+ UntrustedToAllowOriginConfigConfig:: isSinkWrite ( sink , allowOriginHW )
100125 |
101126 message =
102127 headerAllowOrigin ( ) + " header is set to a user-defined value, and " +
@@ -108,11 +133,17 @@ predicate flowsFromUntrustedToAllowOrigin(AllowOriginHeaderWrite allowOriginHW,
108133 * Holds if the provided `allowOriginHW` HeaderWrite is for a `Access-Control-Allow-Origin`
109134 * header and the value is set to `null`.
110135 */
111- predicate allowOriginIsNull ( AllowOriginHeaderWrite allowOriginHW , string message ) {
112- allowOriginHW .getHeaderValue ( ) .toLowerCase ( ) = "null" and
136+ predicate allowOriginIsNull ( DataFlow :: ExprNode allowOrigin , string message ) {
137+ allowOrigin . ( AllowOriginHeaderWrite ) .getHeaderValue ( ) .toLowerCase ( ) = "null" and
113138 message =
114- headerAllowOrigin ( ) + " header is set to `" + allowOriginHW .getHeaderValue ( ) + "`, and " +
139+ headerAllowOrigin ( ) + " header is set to `" + allowOrigin . ( AllowOriginHeaderWrite ) .getHeaderValue ( ) + "`, and " +
115140 headerAllowCredentials ( ) + " is set to `true`"
141+ or
142+ allowOrigin .( GinCors:: AllowOriginsWrite ) .asExpr ( ) .( SliceLit ) .getAnElement ( ) .toString ( ) .matches ( "\"null%\"" ) and
143+ message =
144+ headerAllowOrigin ( ) + " header is set to `" + allowOrigin .( GinCors:: AllowOriginsWrite ) .asExpr ( ) .( SliceLit ) .getAnElement ( ) .toString ( ) + "`, and " +
145+ headerAllowCredentials ( ) + " is set to `true`"
146+
116147}
117148
118149/**
@@ -170,26 +201,26 @@ module FromUntrustedFlow = TaintTracking::Global<FromUntrustedConfig>;
170201/**
171202 * Holds if the provided `allowOriginHW` is also destination of a `UntrustedFlowSource`.
172203 */
173- predicate flowsToGuardedByCheckOnUntrusted ( AllowOriginHeaderWrite allowOriginHW ) {
204+ predicate flowsToGuardedByCheckOnUntrusted ( DataFlow :: ExprNode allowOriginHW ) {
174205 exists ( DataFlow:: Node sink , ControlFlow:: ConditionGuardNode cgn |
175206 FromUntrustedFlow:: flowTo ( sink ) and FromUntrustedConfig:: isSinkCgn ( sink , cgn )
176207 |
177208 cgn .dominates ( allowOriginHW .getBasicBlock ( ) )
178209 )
179210}
180211
181- from AllowOriginHeaderWrite allowOriginHW , string message
212+ from DataFlow :: ExprNode allowOrigin , string message
182213where
183- allowCredentialsIsSetToTrue ( allowOriginHW ) and
214+ allowCredentialsIsSetToTrue ( allowOrigin ) and
184215 (
185- flowsFromUntrustedToAllowOrigin ( allowOriginHW , message )
216+ flowsFromUntrustedToAllowOrigin ( allowOrigin , message )
186217 or
187- allowOriginIsNull ( allowOriginHW , message )
218+ allowOriginIsNull ( allowOrigin , message )
188219 ) and
189- not flowsToGuardedByCheckOnUntrusted ( allowOriginHW ) and
220+ not flowsToGuardedByCheckOnUntrusted ( allowOrigin ) and
190221 not exists ( ControlFlow:: ConditionGuardNode cgn |
191222 cgn .ensures ( any ( AllowedFlag f ) .getAFlag ( ) .getANode ( ) , _)
192223 |
193- cgn .dominates ( allowOriginHW .getBasicBlock ( ) )
224+ cgn .dominates ( allowOrigin .getBasicBlock ( ) )
194225 )
195- select allowOriginHW , message
226+ select allowOrigin , message
0 commit comments