diff --git a/cmd/generate/config/main.go b/cmd/generate/config/main.go index 5d5b6ac91..086eceb34 100644 --- a/cmd/generate/config/main.go +++ b/cmd/generate/config/main.go @@ -70,7 +70,9 @@ func main() { rules.EasyPost(), rules.EasyPostTestAPI(), rules.EtsyAccessToken(), - rules.Facebook(), + rules.FacebookSecret(), + rules.FacebookAccessToken(), + rules.FacebookPageAccessToken(), rules.FastlyAPIToken(), rules.FinicityClientSecret(), rules.FinicityAPIToken(), diff --git a/cmd/generate/config/rules/facebook.go b/cmd/generate/config/rules/facebook.go index 1ddff73be..25bb38b97 100644 --- a/cmd/generate/config/rules/facebook.go +++ b/cmd/generate/config/rules/facebook.go @@ -5,11 +5,13 @@ import ( "github.com/zricethezav/gitleaks/v8/config" ) -func Facebook() *config.Rule { +// This rule includes both App Secret and Client Access Token +// https://developers.facebook.com/docs/facebook-login/guides/access-tokens/ +func FacebookSecret() *config.Rule { // define rule r := config.Rule{ - Description: "Discovered a Facebook Access Token, posing a risk of unauthorized access to Facebook accounts and personal data exposure.", - RuleID: "facebook", + Description: "Discovered a Facebook Application secret, posing a risk of unauthorized access to Facebook accounts and personal data exposure.", + RuleID: "facebook-secret", Regex: generateSemiGenericRegex([]string{"facebook"}, hex("32"), true), Keywords: []string{"facebook"}, @@ -18,6 +20,46 @@ func Facebook() *config.Rule { // validate tps := []string{ generateSampleSecret("facebook", secrets.NewSecret(hex("32"))), + `facebook_app_secret = "6dca6432e45d933e13650d1882bd5e69"`, // gitleaks:allow + `facebook_client_access_token: 26f5fd13099f2c1331aafb86f6489692`, // gitleaks:allow + } + return validate(r, tps, nil) +} + +// https://developers.facebook.com/docs/facebook-login/guides/access-tokens/#apptokens +func FacebookAccessToken() *config.Rule { + // define rule + r := config.Rule{ + Description: "Discovered a Facebook Access Token, posing a risk of unauthorized access to Facebook accounts and personal data exposure.", + RuleID: "facebook-access-token", + Regex: generateUniqueTokenRegex(`\d{15,16}\|[0-9a-z\-_]{27}`, true), + } + + // validate + tps := []string{ + `{"access_token":"911602140448729|AY-lRJZq9BoDLobvAiP25L7RcMg","token_type":"bearer"}`, // gitleaks:allow + `1308742762612587|rhoK1cbv0DOU_RTX_87O4MkX7AI`, // gitleaks:allow + `1477036645700765|wRPf2v3mt2JfMqCLK8n7oltrEmc`, // gitleaks:allow + } + return validate(r, tps, nil) +} + +// https://developers.facebook.com/docs/facebook-login/guides/access-tokens/#pagetokens +func FacebookPageAccessToken() *config.Rule { + // define rule + r := config.Rule{ + Description: "Discovered a Facebook Page Access Token, posing a risk of unauthorized access to Facebook accounts and personal data exposure.", + RuleID: "facebook-page-access-token", + Regex: generateUniqueTokenRegex("EAA[MC]"+alphaNumeric("20,"), true), + Keywords: []string{"EAAM", "EAAC"}, + } + + // validate + tps := []string{ + `EAAM9GOnCB9kBO2frzOAWGN2zMnZClQshlWydZCrBNdodesbwimx1mfVJgqZBP5RSpMfUzWhtjTTXHG5I1UlvlwRZCgjm3ZBVGeTYiqAAoxyED6HaUdhpGVNoPUwAuAWWFsi9OvyYBQt22DGLqMIgD7VktuCTTZCWKasz81Q822FPhMTB9VFFyClNzQ0NLZClt9zxpsMMrUZCo1VU1rL3CKavir5QTfBjfCEzHNlWAUDUV2YZD`, // gitleaks:allow + `EAAM9GOnCB9kBO2zXpAtRBmCrsPPjdA3KeBl4tqsEpcYd09cpjm9MZCBIklZBjIQBKGIJgFwm8IE17G5pipsfRBRBEHMWxvJsL7iHLUouiprxKRQfAagw8BEEDucceqxTiDhVW2IZAQNNbf0d1JhcapAGntx5S1Csm4j0GgZB3DuUfI2HJ9aViTtdfH2vjBy0wtpXm2iamevohGfoF4NgyRHusDLjqy91uYMkfrkc`, // gitleaks:allow + `- name: FACEBOOK_TOKEN + value: "EAACEdEose0cBA1bad3afsf2aew"`, // gitleaks:allow } return validate(r, tps, nil) } diff --git a/cmd/generate/config/rules/mailchimp.go b/cmd/generate/config/rules/mailchimp.go index fe2f8a8dd..6dca25792 100644 --- a/cmd/generate/config/rules/mailchimp.go +++ b/cmd/generate/config/rules/mailchimp.go @@ -10,7 +10,7 @@ func MailChimp() *config.Rule { r := config.Rule{ RuleID: "mailchimp-api-key", Description: "Identified a Mailchimp API key, potentially compromising email marketing campaigns and subscriber data.", - Regex: generateSemiGenericRegex([]string{"mailchimp"}, `[a-f0-9]{32}-us20`, true), + Regex: generateSemiGenericRegex([]string{"MailchimpSDK.initialize", "mailchimp"}, hex("32")+`-us\d\d`, true), Keywords: []string{ "mailchimp", @@ -20,6 +20,12 @@ func MailChimp() *config.Rule { // validate tps := []string{ generateSampleSecret("mailchimp", secrets.NewSecret(hex("32"))+"-us20"), + `mailchimp_api_key: cefa780880ba5f5696192a34f6292c35-us18`, // gitleaks:allow + `MAILCHIMPE_KEY = "b5b9f8e50c640da28993e8b6a48e3e53-us18"`, // gitleaks:allow } - return validate(r, tps, nil) + fps := []string{ + // False Negative + `MailchimpSDK.initialize(token: 3012a5754bbd716926f99c028f7ea428-us18)`, // gitleaks:allow + } + return validate(r, tps, fps) } diff --git a/cmd/generate/config/rules/square.go b/cmd/generate/config/rules/square.go index 84cc8dda4..bf5796d82 100644 --- a/cmd/generate/config/rules/square.go +++ b/cmd/generate/config/rules/square.go @@ -10,13 +10,15 @@ func SquareAccessToken() *config.Rule { r := config.Rule{ RuleID: "square-access-token", Description: "Detected a Square Access Token, risking unauthorized payment processing and financial transaction exposure.", - Regex: generateUniqueTokenRegex(`sq0atp-[0-9A-Za-z\-_]{22}`, true), - Keywords: []string{"sq0atp-"}, + Regex: generateUniqueTokenRegex(`(EAAA|sq0atp-)[0-9A-Za-z\-_]{22,60}`, true), + Keywords: []string{"sq0atp-", "EAAA"}, } // validate tps := []string{ generateSampleSecret("square", secrets.NewSecret(`sq0atp-[0-9A-Za-z\-_]{22}`)), + "ARG token=sq0atp-812erere3wewew45678901", // gitleaks:allow + "ARG token=EAAAlsBxkkVgvmr7FasTFbM6VUGZ31EJ4jZKTJZySgElBDJ_wyafHuBFquFexY7E", // gitleaks:allow", } return validate(r, tps, nil) } @@ -33,6 +35,7 @@ func SquareSecret() *config.Rule { // validate tps := []string{ generateSampleSecret("square", secrets.NewSecret(`sq0csp-[0-9A-Za-z\\-_]{43}`)), + `value: "sq0csp-0p9h7g6f4s3s3s3-4a3ardgwa6ADRDJDDKUFYDYDYDY"`, // gitleaks:allow } return validate(r, tps, nil) } diff --git a/config/config.go b/config/config.go index a7980ecec..e3706e01a 100644 --- a/config/config.go +++ b/config/config.go @@ -4,6 +4,7 @@ import ( _ "embed" "fmt" "regexp" + "sort" "strings" "github.com/rs/zerolog/log" @@ -62,7 +63,7 @@ type Config struct { Keywords []string // used to keep sarif results consistent - orderedRules []string + OrderedRules []string } // Extend is a struct that allows users to define how they want their @@ -158,7 +159,7 @@ func (vc *ViperConfig) Translate() (Config, error) { StopWords: vc.Allowlist.StopWords, }, Keywords: keywords, - orderedRules: orderedRules, + OrderedRules: orderedRules, } if maxExtendDepth != extendDepth { @@ -177,9 +178,9 @@ func (vc *ViperConfig) Translate() (Config, error) { return c, nil } -func (c *Config) OrderedRules() []Rule { +func (c *Config) GetOrderedRules() []Rule { var orderedRules []Rule - for _, id := range c.orderedRules { + for _, id := range c.OrderedRules { if _, ok := c.Rules[id]; ok { orderedRules = append(orderedRules, c.Rules[id]) } @@ -240,6 +241,7 @@ func (c *Config) extend(extensionConfig Config) { log.Trace().Msgf("adding %s to base config", ruleID) c.Rules[ruleID] = rule c.Keywords = append(c.Keywords, rule.Keywords...) + c.OrderedRules = append(c.OrderedRules, ruleID) } } @@ -250,4 +252,7 @@ func (c *Config) extend(extensionConfig Config) { extensionConfig.Allowlist.Paths...) c.Allowlist.Regexes = append(c.Allowlist.Regexes, extensionConfig.Allowlist.Regexes...) + + // sort to keep extended rules in order + sort.Strings(c.OrderedRules) } diff --git a/config/gitleaks.toml b/config/gitleaks.toml index e5bd7d28f..02e0cd090 100644 --- a/config/gitleaks.toml +++ b/config/gitleaks.toml @@ -394,8 +394,21 @@ keywords = [ ] [[rules]] -id = "facebook" +id = "facebook-access-token" description = "Discovered a Facebook Access Token, posing a risk of unauthorized access to Facebook accounts and personal data exposure." +regex = '''(?i)\b(\d{15,16}\|[0-9a-z\-_]{27})(?:['|\"|\n|\r|\s|\x60|;]|$)''' + +[[rules]] +id = "facebook-page-access-token" +description = "Discovered a Facebook Page Access Token, posing a risk of unauthorized access to Facebook accounts and personal data exposure." +regex = '''(?i)\b(EAA[MC][a-z0-9]{20,})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +keywords = [ + "eaam","eaac", +] + +[[rules]] +id = "facebook-secret" +description = "Discovered a Facebook Application secret, posing a risk of unauthorized access to Facebook accounts and personal data exposure." regex = '''(?i)(?:facebook)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-f0-9]{32})(?:['|\"|\n|\r|\s|\x60|;]|$)''' keywords = [ "facebook", @@ -2261,7 +2274,7 @@ keywords = [ [[rules]] id = "mailchimp-api-key" description = "Identified a Mailchimp API key, potentially compromising email marketing campaigns and subscriber data." -regex = '''(?i)(?:mailchimp)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-f0-9]{32}-us20)(?:['|\"|\n|\r|\s|\x60|;]|$)''' +regex = '''(?i)(?:MailchimpSDK.initialize|mailchimp)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|\"|\s|=|\x60){0,5}([a-f0-9]{32}-us\d\d)(?:['|\"|\n|\r|\s|\x60|;]|$)''' keywords = [ "mailchimp", ] @@ -2696,9 +2709,9 @@ keywords = [ [[rules]] id = "square-access-token" description = "Detected a Square Access Token, risking unauthorized payment processing and financial transaction exposure." -regex = '''(?i)\b(sq0atp-[0-9A-Za-z\-_]{22})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +regex = '''(?i)\b((EAAA|sq0atp-)[0-9A-Za-z\-_]{22,60})(?:['|\"|\n|\r|\s|\x60|;]|$)''' keywords = [ - "sq0atp-", + "sq0atp-","eaaa", ] [[rules]] diff --git a/report/sarif.go b/report/sarif.go index 732e0463d..c6b1af1fa 100644 --- a/report/sarif.go +++ b/report/sarif.go @@ -55,7 +55,7 @@ func hasEmptyRules(tool Tool) bool { func getRules(cfg config.Config) []Rules { // TODO for _, rule := range cfg.Rules { var rules []Rules - for _, rule := range cfg.OrderedRules() { + for _, rule := range cfg.GetOrderedRules() { shortDescription := ShortDescription{ Text: rule.Description, }