From 0ee7bbbaa7ff76efd06c82681e11f95c83babbbd Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Tue, 18 Aug 2020 15:22:01 +0100 Subject: [PATCH] Extend oauth2 tests --- .../CWE-352/ConstantOauth2State.expected | 89 ++++++++----- .../CWE-352/ConstantOauth2State.go | 118 ++++++++++++++++++ 2 files changed, 175 insertions(+), 32 deletions(-) diff --git a/ql/test/experimental/CWE-352/ConstantOauth2State.expected b/ql/test/experimental/CWE-352/ConstantOauth2State.expected index ecd1543cd1a..8e7dc5d59de 100644 --- a/ql/test/experimental/CWE-352/ConstantOauth2State.expected +++ b/ql/test/experimental/CWE-352/ConstantOauth2State.expected @@ -1,35 +1,60 @@ edges -| ConstantOauth2State.go:18:26:18:32 | "state" : string literal | ConstantOauth2State.go:48:26:48:41 | stateStringConst | -| ConstantOauth2State.go:18:26:18:32 | "state" : string literal | ConstantOauth2State.go:145:26:145:41 | stateStringConst | -| ConstantOauth2State.go:18:26:18:32 | "state" : string literal | ConstantOauth2State.go:167:26:167:41 | stateStringConst | -| ConstantOauth2State.go:18:26:18:32 | "state" : string literal | ConstantOauth2State.go:189:26:189:41 | stateStringConst | -| ConstantOauth2State.go:20:22:20:28 | "state" : string | ConstantOauth2State.go:63:26:63:39 | stateStringVar | -| ConstantOauth2State.go:78:11:78:25 | call to newFixedState : string | ConstantOauth2State.go:79:26:79:30 | state | -| ConstantOauth2State.go:84:9:84:15 | "state" : string | ConstantOauth2State.go:78:11:78:25 | call to newFixedState : string | -| ConstantOauth2State.go:145:9:145:42 | call to AuthCodeURL : string | ConstantOauth2State.go:146:54:146:56 | url | -| ConstantOauth2State.go:167:9:167:42 | call to AuthCodeURL : string | ConstantOauth2State.go:168:54:168:56 | url | -| ConstantOauth2State.go:189:9:189:42 | call to AuthCodeURL : string | ConstantOauth2State.go:190:28:190:30 | url | +| ConstantOauth2State.go:20:26:20:32 | "state" : string literal | ConstantOauth2State.go:50:26:50:41 | stateStringConst | +| ConstantOauth2State.go:20:26:20:32 | "state" : string literal | ConstantOauth2State.go:147:26:147:41 | stateStringConst | +| ConstantOauth2State.go:20:26:20:32 | "state" : string literal | ConstantOauth2State.go:169:26:169:41 | stateStringConst | +| ConstantOauth2State.go:20:26:20:32 | "state" : string literal | ConstantOauth2State.go:191:26:191:41 | stateStringConst | +| ConstantOauth2State.go:20:26:20:32 | "state" : string literal | ConstantOauth2State.go:210:26:210:41 | stateStringConst | +| ConstantOauth2State.go:20:26:20:32 | "state" : string literal | ConstantOauth2State.go:232:26:232:41 | stateStringConst | +| ConstantOauth2State.go:20:26:20:32 | "state" : string literal | ConstantOauth2State.go:249:26:249:41 | stateStringConst | +| ConstantOauth2State.go:20:26:20:32 | "state" : string literal | ConstantOauth2State.go:266:26:266:41 | stateStringConst | +| ConstantOauth2State.go:20:26:20:32 | "state" : string literal | ConstantOauth2State.go:282:26:282:41 | stateStringConst | +| ConstantOauth2State.go:22:22:22:28 | "state" : string | ConstantOauth2State.go:65:26:65:39 | stateStringVar | +| ConstantOauth2State.go:80:11:80:25 | call to newFixedState : string | ConstantOauth2State.go:81:26:81:30 | state | +| ConstantOauth2State.go:86:9:86:15 | "state" : string | ConstantOauth2State.go:80:11:80:25 | call to newFixedState : string | +| ConstantOauth2State.go:147:9:147:42 | call to AuthCodeURL : string | ConstantOauth2State.go:148:54:148:56 | url | +| ConstantOauth2State.go:169:9:169:42 | call to AuthCodeURL : string | ConstantOauth2State.go:170:54:170:56 | url | +| ConstantOauth2State.go:191:9:191:42 | call to AuthCodeURL : string | ConstantOauth2State.go:192:54:192:56 | url | +| ConstantOauth2State.go:210:9:210:42 | call to AuthCodeURL : string | ConstantOauth2State.go:211:54:211:56 | url | +| ConstantOauth2State.go:232:9:232:42 | call to AuthCodeURL : string | ConstantOauth2State.go:233:28:233:30 | url | +| ConstantOauth2State.go:239:17:239:39 | "http://localhost:8080" : string | ConstantOauth2State.go:249:9:249:12 | conf | +| ConstantOauth2State.go:256:38:256:60 | "http://localhost:8080" : string | ConstantOauth2State.go:266:9:266:12 | conf | +| ConstantOauth2State.go:272:17:272:21 | "oob" : string | ConstantOauth2State.go:282:9:282:12 | conf | nodes -| ConstantOauth2State.go:18:26:18:32 | "state" : string literal | semmle.label | "state" : string literal | -| ConstantOauth2State.go:20:22:20:28 | "state" : string | semmle.label | "state" : string | -| ConstantOauth2State.go:33:26:33:32 | "state" | semmle.label | "state" | -| ConstantOauth2State.go:48:26:48:41 | stateStringConst | semmle.label | stateStringConst | -| ConstantOauth2State.go:63:26:63:39 | stateStringVar | semmle.label | stateStringVar | -| ConstantOauth2State.go:78:11:78:25 | call to newFixedState : string | semmle.label | call to newFixedState : string | -| ConstantOauth2State.go:79:26:79:30 | state | semmle.label | state | -| ConstantOauth2State.go:84:9:84:15 | "state" : string | semmle.label | "state" : string | -| ConstantOauth2State.go:145:9:145:42 | call to AuthCodeURL : string | semmle.label | call to AuthCodeURL : string | -| ConstantOauth2State.go:145:26:145:41 | stateStringConst | semmle.label | stateStringConst | -| ConstantOauth2State.go:146:54:146:56 | url | semmle.label | url | -| ConstantOauth2State.go:167:9:167:42 | call to AuthCodeURL : string | semmle.label | call to AuthCodeURL : string | -| ConstantOauth2State.go:167:26:167:41 | stateStringConst | semmle.label | stateStringConst | -| ConstantOauth2State.go:168:54:168:56 | url | semmle.label | url | -| ConstantOauth2State.go:189:9:189:42 | call to AuthCodeURL : string | semmle.label | call to AuthCodeURL : string | -| ConstantOauth2State.go:189:26:189:41 | stateStringConst | semmle.label | stateStringConst | -| ConstantOauth2State.go:190:28:190:30 | url | semmle.label | url | +| ConstantOauth2State.go:20:26:20:32 | "state" : string literal | semmle.label | "state" : string literal | +| ConstantOauth2State.go:22:22:22:28 | "state" : string | semmle.label | "state" : string | +| ConstantOauth2State.go:35:26:35:32 | "state" | semmle.label | "state" | +| ConstantOauth2State.go:50:26:50:41 | stateStringConst | semmle.label | stateStringConst | +| ConstantOauth2State.go:65:26:65:39 | stateStringVar | semmle.label | stateStringVar | +| ConstantOauth2State.go:80:11:80:25 | call to newFixedState : string | semmle.label | call to newFixedState : string | +| ConstantOauth2State.go:81:26:81:30 | state | semmle.label | state | +| ConstantOauth2State.go:86:9:86:15 | "state" : string | semmle.label | "state" : string | +| ConstantOauth2State.go:147:9:147:42 | call to AuthCodeURL : string | semmle.label | call to AuthCodeURL : string | +| ConstantOauth2State.go:147:26:147:41 | stateStringConst | semmle.label | stateStringConst | +| ConstantOauth2State.go:148:54:148:56 | url | semmle.label | url | +| ConstantOauth2State.go:169:9:169:42 | call to AuthCodeURL : string | semmle.label | call to AuthCodeURL : string | +| ConstantOauth2State.go:169:26:169:41 | stateStringConst | semmle.label | stateStringConst | +| ConstantOauth2State.go:170:54:170:56 | url | semmle.label | url | +| ConstantOauth2State.go:191:9:191:42 | call to AuthCodeURL : string | semmle.label | call to AuthCodeURL : string | +| ConstantOauth2State.go:191:26:191:41 | stateStringConst | semmle.label | stateStringConst | +| ConstantOauth2State.go:192:54:192:56 | url | semmle.label | url | +| ConstantOauth2State.go:210:9:210:42 | call to AuthCodeURL : string | semmle.label | call to AuthCodeURL : string | +| ConstantOauth2State.go:210:26:210:41 | stateStringConst | semmle.label | stateStringConst | +| ConstantOauth2State.go:211:54:211:56 | url | semmle.label | url | +| ConstantOauth2State.go:232:9:232:42 | call to AuthCodeURL : string | semmle.label | call to AuthCodeURL : string | +| ConstantOauth2State.go:232:26:232:41 | stateStringConst | semmle.label | stateStringConst | +| ConstantOauth2State.go:233:28:233:30 | url | semmle.label | url | +| ConstantOauth2State.go:239:17:239:39 | "http://localhost:8080" : string | semmle.label | "http://localhost:8080" : string | +| ConstantOauth2State.go:249:9:249:12 | conf | semmle.label | conf | +| ConstantOauth2State.go:249:26:249:41 | stateStringConst | semmle.label | stateStringConst | +| ConstantOauth2State.go:256:38:256:60 | "http://localhost:8080" : string | semmle.label | "http://localhost:8080" : string | +| ConstantOauth2State.go:266:9:266:12 | conf | semmle.label | conf | +| ConstantOauth2State.go:266:26:266:41 | stateStringConst | semmle.label | stateStringConst | +| ConstantOauth2State.go:272:17:272:21 | "oob" : string | semmle.label | "oob" : string | +| ConstantOauth2State.go:282:9:282:12 | conf | semmle.label | conf | +| ConstantOauth2State.go:282:26:282:41 | stateStringConst | semmle.label | stateStringConst | #select -| ConstantOauth2State.go:33:26:33:32 | "state" | ConstantOauth2State.go:33:26:33:32 | "state" | ConstantOauth2State.go:33:26:33:32 | "state" | Using a constant $@ to create oauth2 URLs. | ConstantOauth2State.go:33:26:33:32 | "state" | state string | -| ConstantOauth2State.go:48:26:48:41 | stateStringConst | ConstantOauth2State.go:18:26:18:32 | "state" : string literal | ConstantOauth2State.go:48:26:48:41 | stateStringConst | Using a constant $@ to create oauth2 URLs. | ConstantOauth2State.go:18:26:18:32 | "state" | state string | -| ConstantOauth2State.go:63:26:63:39 | stateStringVar | ConstantOauth2State.go:20:22:20:28 | "state" : string | ConstantOauth2State.go:63:26:63:39 | stateStringVar | Using a constant $@ to create oauth2 URLs. | ConstantOauth2State.go:20:22:20:28 | "state" | state string | -| ConstantOauth2State.go:79:26:79:30 | state | ConstantOauth2State.go:84:9:84:15 | "state" : string | ConstantOauth2State.go:79:26:79:30 | state | Using a constant $@ to create oauth2 URLs. | ConstantOauth2State.go:84:9:84:15 | "state" | state string | -| ConstantOauth2State.go:189:26:189:41 | stateStringConst | ConstantOauth2State.go:18:26:18:32 | "state" : string literal | ConstantOauth2State.go:189:26:189:41 | stateStringConst | Using a constant $@ to create oauth2 URLs. | ConstantOauth2State.go:18:26:18:32 | "state" | state string | +| ConstantOauth2State.go:35:26:35:32 | "state" | ConstantOauth2State.go:35:26:35:32 | "state" | ConstantOauth2State.go:35:26:35:32 | "state" | Using a constant $@ to create oauth2 URLs. | ConstantOauth2State.go:35:26:35:32 | "state" | state string | +| ConstantOauth2State.go:50:26:50:41 | stateStringConst | ConstantOauth2State.go:20:26:20:32 | "state" : string literal | ConstantOauth2State.go:50:26:50:41 | stateStringConst | Using a constant $@ to create oauth2 URLs. | ConstantOauth2State.go:20:26:20:32 | "state" | state string | +| ConstantOauth2State.go:65:26:65:39 | stateStringVar | ConstantOauth2State.go:22:22:22:28 | "state" : string | ConstantOauth2State.go:65:26:65:39 | stateStringVar | Using a constant $@ to create oauth2 URLs. | ConstantOauth2State.go:22:22:22:28 | "state" | state string | +| ConstantOauth2State.go:81:26:81:30 | state | ConstantOauth2State.go:86:9:86:15 | "state" : string | ConstantOauth2State.go:81:26:81:30 | state | Using a constant $@ to create oauth2 URLs. | ConstantOauth2State.go:86:9:86:15 | "state" | state string | +| ConstantOauth2State.go:232:26:232:41 | stateStringConst | ConstantOauth2State.go:20:26:20:32 | "state" : string literal | ConstantOauth2State.go:232:26:232:41 | stateStringConst | Using a constant $@ to create oauth2 URLs. | ConstantOauth2State.go:20:26:20:32 | "state" | state string | diff --git a/ql/test/experimental/CWE-352/ConstantOauth2State.go b/ql/test/experimental/CWE-352/ConstantOauth2State.go index b3200670fb9..75f899aea51 100644 --- a/ql/test/experimental/CWE-352/ConstantOauth2State.go +++ b/ql/test/experimental/CWE-352/ConstantOauth2State.go @@ -3,8 +3,10 @@ package main //go:generate depstubber -vendor golang.org/x/oauth2 Config,Endpoint import ( + "bufio" "crypto/rand" "encoding/base64" + "errors" "fmt" "log" "net/http" @@ -175,6 +177,47 @@ func okWithConstStateFPrinter(w http.ResponseWriter) { _ = code // ... } +func okWithConstStateBufio(w http.ResponseWriter) { + conf := &oauth2.Config{ + ClientID: "YOUR_CLIENT_ID", + ClientSecret: "YOUR_CLIENT_SECRET", + Scopes: []string{"SCOPE1", "SCOPE2"}, + Endpoint: oauth2.Endpoint{ + AuthURL: "https://provider.com/o/oauth2/auth", + TokenURL: "https://provider.com/o/oauth2/token", + }, + } + + url := conf.AuthCodeURL(stateStringConst) // OK, because we're supposedly not exposed to the web, but within a terminal. + fmt.Printf("Visit the URL for the auth dialog: %v", url) + // ... + + scanner := bufio.NewScanner(os.Stdin) + _ = scanner + // ... +} +func okWithConstStateLogger(w http.ResponseWriter) { + conf := &oauth2.Config{ + ClientID: "YOUR_CLIENT_ID", + ClientSecret: "YOUR_CLIENT_SECRET", + Scopes: []string{"SCOPE1", "SCOPE2"}, + Endpoint: oauth2.Endpoint{ + AuthURL: "https://provider.com/o/oauth2/auth", + TokenURL: "https://provider.com/o/oauth2/token", + }, + } + + url := conf.AuthCodeURL(stateStringConst) // OK, because we're supposedly not exposed to the web, but within a terminal. + log.Printf("Visit the URL for the auth dialog: %v", url) + // ... + + var code string + if _, err := fmt.Fscan(os.Stdin, &code); err != nil { + log.Fatal(err) + } + _ = code + // ... +} func badWithConstStatePrinter(w http.ResponseWriter) { conf := &oauth2.Config{ ClientID: "YOUR_CLIENT_ID", @@ -190,3 +233,78 @@ func badWithConstStatePrinter(w http.ResponseWriter) { fmt.Printf("LOG: URL %v", url) // ... } + +func okWithLocalUrl(w http.ResponseWriter) { + conf := &oauth2.Config{ + RedirectURL: "http://localhost:8080", + ClientID: "YOUR_CLIENT_ID", + ClientSecret: "YOUR_CLIENT_SECRET", + Scopes: []string{"SCOPE1", "SCOPE2"}, + Endpoint: oauth2.Endpoint{ + AuthURL: "https://provider.com/o/oauth2/auth", + TokenURL: "https://provider.com/o/oauth2/token", + }, + } + + url := conf.AuthCodeURL(stateStringConst) // OK because the config uses a local url + _ = url +} + +func okWithLocalUrlSprintf(w http.ResponseWriter) { + port := 8080 + conf := &oauth2.Config{ + RedirectURL: fmt.Sprintf("%s:%d", "http://localhost:8080", port), + ClientID: "YOUR_CLIENT_ID", + ClientSecret: "YOUR_CLIENT_SECRET", + Scopes: []string{"SCOPE1", "SCOPE2"}, + Endpoint: oauth2.Endpoint{ + AuthURL: "https://provider.com/o/oauth2/auth", + TokenURL: "https://provider.com/o/oauth2/token", + }, + } + + url := conf.AuthCodeURL(stateStringConst) // OK because the config uses a local url + _ = url +} + +func okWithOutOfBoundsToken(w http.ResponseWriter) { + conf := &oauth2.Config{ + RedirectURL: "oob", + ClientID: "YOUR_CLIENT_ID", + ClientSecret: "YOUR_CLIENT_SECRET", + Scopes: []string{"SCOPE1", "SCOPE2"}, + Endpoint: oauth2.Endpoint{ + AuthURL: "https://provider.com/o/oauth2/auth", + TokenURL: "https://provider.com/o/oauth2/token", + }, + } + + url := conf.AuthCodeURL(stateStringConst) // OK because the config uses a token indicating out-of-band communication + _ = url +} + +func tryGetState(success bool) (string, string, int, error) { + if success { + return NewCSRFToken(), "dummy", 0, nil + } else { + return "", "", 0, errors.New("success not set") + } +} + +func okConstantOnlySuppliedAlongsideError(w http.ResponseWriter) { + conf := &oauth2.Config{ + ClientID: "YOUR_CLIENT_ID", + ClientSecret: "YOUR_CLIENT_SECRET", + Scopes: []string{"SCOPE1", "SCOPE2"}, + Endpoint: oauth2.Endpoint{ + AuthURL: "https://provider.com/o/oauth2/auth", + TokenURL: "https://provider.com/o/oauth2/token", + }, + } + + token, _, _, err := tryGetState(len(os.Args)%3 == 1) + if err != nil { + url := conf.AuthCodeURL(token) // OK because constant states coming from tryGetState only occur with errors + _ = url + } +}