1212 */
1313
1414import go
15- import DataFlow:: PathGraph
1615
1716/**
1817 * A method that creates a new URL that will send the user
@@ -24,18 +23,12 @@ class AuthCodeUrl extends Method {
2423 }
2524}
2625
27- /**
28- * A flow of a constant string value to a call to `AuthCodeURL` as the
29- * `state` parameter.
30- */
31- class ConstantStateFlowConf extends DataFlow:: Configuration {
32- ConstantStateFlowConf ( ) { this = "ConstantStateFlowConf" }
33-
34- predicate isSinkCall ( DataFlow:: Node sink , DataFlow:: CallNode call ) {
26+ module ConstantStateFlowConfig implements DataFlow:: ConfigSig {
27+ additional predicate isSinkCall ( DataFlow:: Node sink , DataFlow:: CallNode call ) {
3528 exists ( AuthCodeUrl m | call = m .getACall ( ) | sink = call .getArgument ( 0 ) )
3629 }
3730
38- override predicate isSource ( DataFlow:: Node source ) {
31+ predicate isSource ( DataFlow:: Node source ) {
3932 source .isConst ( ) and
4033 not DataFlow:: isReturnedWithError ( source ) and
4134 // Avoid duplicate paths by not considering reads from constants as sources themselves:
@@ -46,9 +39,13 @@ class ConstantStateFlowConf extends DataFlow::Configuration {
4639 )
4740 }
4841
49- override predicate isSink ( DataFlow:: Node sink ) { this . isSinkCall ( sink , _) }
42+ predicate isSink ( DataFlow:: Node sink ) { isSinkCall ( sink , _) }
5043}
5144
45+ module Flow = DataFlow:: Global< ConstantStateFlowConfig > ;
46+
47+ import Flow:: PathGraph
48+
5249/**
5350 * Holds if `pred` writes a URL to the `RedirectURL` field of the `succ` `Config` object.
5451 *
@@ -77,17 +74,8 @@ string getAnOobOauth2Url() {
7774 result .matches ( "%://127.0.0.1%" )
7875}
7976
80- /**
81- * A flow of a URL indicating the OAuth redirect doesn't point to a publicly
82- * accessible address, to the receiver of an `AuthCodeURL` call.
83- *
84- * Note we accept localhost and 127.0.0.1 on the assumption this is probably a transient
85- * listener; if it actually is a persistent server then that really is vulnerable to CSRF.
86- */
87- class PrivateUrlFlowsToAuthCodeUrlCall extends DataFlow:: Configuration {
88- PrivateUrlFlowsToAuthCodeUrlCall ( ) { this = "PrivateUrlFlowsToConfig" }
89-
90- override predicate isSource ( DataFlow:: Node source ) {
77+ module PrivateUrlFlowsToAuthCodeUrlCallConfig implements DataFlow:: ConfigSig {
78+ predicate isSource ( DataFlow:: Node source ) {
9179 source .getStringValue ( ) = getAnOobOauth2Url ( ) and
9280 // Avoid duplicate paths by excluding constant variable references from
9381 // themselves being sources:
@@ -98,7 +86,7 @@ class PrivateUrlFlowsToAuthCodeUrlCall extends DataFlow::Configuration {
9886 )
9987 }
10088
101- override predicate isAdditionalFlowStep ( DataFlow:: Node pred , DataFlow:: Node succ ) {
89+ predicate isAdditionalFlowStep ( DataFlow:: Node pred , DataFlow:: Node succ ) {
10290 // Propagate from a RedirectURL field to a whole Config
10391 isUrlTaintingConfigStep ( pred , succ )
10492 or
@@ -113,13 +101,16 @@ class PrivateUrlFlowsToAuthCodeUrlCall extends DataFlow::Configuration {
113101 )
114102 }
115103
116- predicate isSinkCall ( DataFlow:: Node sink , DataFlow:: CallNode call ) {
104+ additional predicate isSinkCall ( DataFlow:: Node sink , DataFlow:: CallNode call ) {
117105 exists ( AuthCodeUrl m | call = m .getACall ( ) | sink = call .getReceiver ( ) )
118106 }
119107
120- override predicate isSink ( DataFlow:: Node sink ) { this . isSinkCall ( sink , _) }
108+ predicate isSink ( DataFlow:: Node sink ) { isSinkCall ( sink , _) }
121109}
122110
111+ module PrivateUrlFlowsToAuthCodeUrlCallFlow =
112+ DataFlow:: Global< PrivateUrlFlowsToAuthCodeUrlCallConfig > ;
113+
123114/**
124115 * Holds if a URL indicating the OAuth redirect doesn't point to a publicly
125116 * accessible address, to the receiver of an `AuthCodeURL` call.
@@ -128,33 +119,27 @@ class PrivateUrlFlowsToAuthCodeUrlCall extends DataFlow::Configuration {
128119 * listener; if it actually is a persistent server then that really is vulnerable to CSRF.
129120 */
130121predicate privateUrlFlowsToAuthCodeUrlCall ( DataFlow:: CallNode call ) {
131- exists ( PrivateUrlFlowsToAuthCodeUrlCall flowConfig , DataFlow:: Node receiver |
132- flowConfig . hasFlowTo ( receiver ) and
133- flowConfig . isSinkCall ( receiver , call )
122+ exists ( DataFlow:: Node receiver |
123+ PrivateUrlFlowsToAuthCodeUrlCallFlow :: flowTo ( receiver ) and
124+ PrivateUrlFlowsToAuthCodeUrlCallConfig :: isSinkCall ( receiver , call )
134125 )
135126}
136127
137- /** A flow from `golang.org/x/oauth2.Config.AuthCodeUrl`'s result to a logging function. */
138- class FlowToPrint extends DataFlow:: Configuration {
139- FlowToPrint ( ) { this = "FlowToPrint" }
140-
141- predicate isSinkCall ( DataFlow:: Node sink , DataFlow:: CallNode call ) {
128+ module FlowToPrintConfig implements DataFlow:: ConfigSig {
129+ additional predicate isSinkCall ( DataFlow:: Node sink , DataFlow:: CallNode call ) {
142130 exists ( LoggerCall logCall | call = logCall | sink = logCall .getAMessageComponent ( ) )
143131 }
144132
145- override predicate isSource ( DataFlow:: Node source ) {
146- source = any ( AuthCodeUrl m ) .getACall ( ) .getResult ( )
147- }
133+ predicate isSource ( DataFlow:: Node source ) { source = any ( AuthCodeUrl m ) .getACall ( ) .getResult ( ) }
148134
149- override predicate isSink ( DataFlow:: Node sink ) { this . isSinkCall ( sink , _) }
135+ predicate isSink ( DataFlow:: Node sink ) { isSinkCall ( sink , _) }
150136}
151137
138+ module FlowToPrintFlow = DataFlow:: Global< FlowToPrintConfig > ;
139+
152140/** Holds if the provided `CallNode`'s result flows to an argument of a printer call. */
153141predicate resultFlowsToPrinter ( DataFlow:: CallNode authCodeUrlCall ) {
154- exists ( FlowToPrint cfg , DataFlow:: PathNode source |
155- cfg .hasFlowPath ( source , _) and
156- authCodeUrlCall .getResult ( ) = source .getNode ( )
157- )
142+ FlowToPrintFlow:: flow ( authCodeUrlCall .getResult ( ) , _)
158143}
159144
160145/** Get a data-flow node that reads the value of `os.Stdin`. */
@@ -197,12 +182,10 @@ predicate seemsLikeDoneWithinATerminal(DataFlow::CallNode authCodeUrlCall) {
197182 containsCallToStdinScanner ( authCodeUrlCall .getRoot ( ) )
198183}
199184
200- from
201- ConstantStateFlowConf cfg , DataFlow:: PathNode source , DataFlow:: PathNode sink ,
202- DataFlow:: CallNode sinkCall
185+ from Flow:: PathNode source , Flow:: PathNode sink , DataFlow:: CallNode sinkCall
203186where
204- cfg . hasFlowPath ( source , sink ) and
205- cfg . isSinkCall ( sink .getNode ( ) , sinkCall ) and
187+ Flow :: flowPath ( source , sink ) and
188+ ConstantStateFlowConfig :: isSinkCall ( sink .getNode ( ) , sinkCall ) and
206189 // Exclude cases that seem to be oauth flows done from within a terminal:
207190 not seemsLikeDoneWithinATerminal ( sinkCall ) and
208191 not privateUrlFlowsToAuthCodeUrlCall ( sinkCall )
0 commit comments