diff --git a/pkg/detectors/appfollow/appfollow.go b/pkg/detectors/appfollow/appfollow.go index a9b6c6355ee5..7e3e37abf0d7 100644 --- a/pkg/detectors/appfollow/appfollow.go +++ b/pkg/detectors/appfollow/appfollow.go @@ -2,8 +2,6 @@ package appfollow import ( "context" - b64 "encoding/base64" - "fmt" "net/http" "regexp" "strings" @@ -22,7 +20,7 @@ var ( client = common.SaneHttpClient() // Make sure that your group is surrounded in boundary characters such as below to reduce false positives. - keyPat = regexp.MustCompile(detectors.PrefixRegex([]string{"appfollow"}) + `\b([0-9A-Za-z]{20})\b`) + keyPat = regexp.MustCompile(detectors.PrefixRegex([]string{"appfollow"}) + `\b(eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9\.[0-9A-Za-z]{74}\.[0-9A-Z-a-z\-_]{43})\b`) ) // Keywords are used for efficiently pre-filtering chunks. @@ -49,13 +47,11 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result } if verify { - data := fmt.Sprintf("%s:", resMatch) - sEnc := b64.StdEncoding.EncodeToString([]byte(data)) - req, err := http.NewRequestWithContext(ctx, "GET", "https://api.appfollow.io/test", nil) + req, err := http.NewRequestWithContext(ctx, "GET", "https://api.appfollow.io/api/v2/account/users", nil) if err != nil { continue } - req.Header.Add("Authorization", fmt.Sprintf("Basic %s", sEnc)) + req.Header.Add("X-AppFollow-API-Token", resMatch) res, err := client.Do(req) if err == nil { defer res.Body.Close() diff --git a/pkg/detectors/redis/redis.go b/pkg/detectors/redis/redis.go index 138f5306967f..5aa4efdd8b0e 100644 --- a/pkg/detectors/redis/redis.go +++ b/pkg/detectors/redis/redis.go @@ -2,6 +2,7 @@ package redis import ( "context" + "fmt" "net/url" "regexp" "strings" @@ -18,7 +19,8 @@ type Scanner struct{} var _ detectors.Detector = (*Scanner)(nil) var ( - keyPat = regexp.MustCompile(`\bredis://[\S]{3,50}:([\S]{3,50})@[-.%\w\/:]+\b`) + keyPat = regexp.MustCompile(`\bredi[s]{1,2}://[\S]{3,50}:([\S]{3,50})@[-.%\w\/:]+\b`) + azureRedisPat = regexp.MustCompile(`\b([\w\d.-]{1,100}\.redis\.cache\.windows\.net:6380),password=([^,]{44}),ssl=True,abortConnect=False\b`) ) // Keywords are used for efficiently pre-filtering chunks. @@ -32,6 +34,51 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result dataStr := string(data) matches := keyPat.FindAllStringSubmatch(dataStr, -1) + azureMatches := azureRedisPat.FindAllStringSubmatch(dataStr, -1) + + for _, match := range azureMatches { + host := match[1] + password := match[2] + urlMatch := fmt.Sprintf("rediss://:%s@%s", password, host) + + // Skip findings where the password only has "*" characters, this is a redacted password + if strings.Trim(password, "*") == "" { + continue + } + + parsedURL, err := url.Parse(urlMatch) + if err != nil { + continue + } + if _, ok := parsedURL.User.Password(); !ok { + continue + } + + redact := strings.TrimSpace(strings.Replace(urlMatch, password, "*******", -1)) + + s := detectors.Result{ + DetectorType: detectorspb.DetectorType_Redis, + Raw: []byte(urlMatch), + Redacted: redact, + } + + if verify { + s.Verified = verifyRedis(ctx, parsedURL) + } + + if !s.Verified { + // Skip unverified findings where the password starts with a `$` - it's almost certainly a variable. + if strings.HasPrefix(password, "$") { + continue + } + } + + if !s.Verified && detectors.IsKnownFalsePositive(string(s.Raw), detectors.DefaultFalsePositives, false) { + continue + } + + results = append(results, s) + } for _, match := range matches { urlMatch := match[0] @@ -50,7 +97,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result continue } - redact := strings.TrimSpace(strings.Replace(urlMatch, password, "********", -1)) + redact := strings.TrimSpace(strings.Replace(urlMatch, password, "*******", -1)) s := detectors.Result{ DetectorType: detectorspb.DetectorType_Redis, diff --git a/pkg/detectors/redis/redis_test.go b/pkg/detectors/redis/redis_test.go index d83db2caf155..92b58dece5a1 100644 --- a/pkg/detectors/redis/redis_test.go +++ b/pkg/detectors/redis/redis_test.go @@ -61,9 +61,6 @@ func TestURI_FromChunk(t *testing.T) { t.Errorf("URI.FromData() error = %v, wantErr %v", err, tt.wantErr) return } - // if os.Getenv("FORCE_PASS_DIFF") == "true" { - // return - // } for i := range got { got[i].Raw = nil }