diff --git a/.gitignore b/.gitignore index 49abd80e2..93ba61b66 100644 --- a/.gitignore +++ b/.gitignore @@ -17,4 +17,4 @@ cmd/generate/config/gitleaks.toml # Test binary *.out -dist/ +dist/ \ No newline at end of file diff --git a/cmd/generate/config/main.go b/cmd/generate/config/main.go index 2211675c1..c3272cdf0 100644 --- a/cmd/generate/config/main.go +++ b/cmd/generate/config/main.go @@ -24,10 +24,37 @@ func main() { configRules = append(configRules, rules.AlgoliaApiKey()) configRules = append(configRules, rules.AlibabaAccessKey()) configRules = append(configRules, rules.AlibabaSecretKey()) + configRules = append(configRules, rules.AnsibleVaultToken()) configRules = append(configRules, rules.AsanaClientID()) configRules = append(configRules, rules.AsanaClientSecret()) configRules = append(configRules, rules.Atlassian()) configRules = append(configRules, rules.AWS()) + configRules = append(configRules, rules.AzureAppServiceDeploymentSecrets()) + configRules = append(configRules, rules.AzureDevTFVCSecrets()) + configRules = append(configRules, rules.AzureDevopsPAT()) + configRules = append(configRules, rules.AzureNetworkCredential()) + configRules = append(configRules, rules.AzureNetworkCredentialSchtasks()) + configRules = append(configRules, rules.AzureNetworkCredentialDotNet()) + configRules = append(configRules, rules.AzurePasswordDecryptionkey()) + configRules = append(configRules, rules.AzurePasswordAddKey()) + configRules = append(configRules, rules.AzurePasswordConnString()) + configRules = append(configRules, rules.AzurePasswordValueString()) + configRules = append(configRules, rules.AzurePassworduidpw()) + configRules = append(configRules, rules.AzureStorageCredential43char()) + configRules = append(configRules, rules.AzureStorageCredential86char()) + configRules = append(configRules, rules.AzureStorageCredentialAccountKey()) + configRules = append(configRules, rules.AzureStorageCredentialBlobURL()) + configRules = append(configRules, rules.AzureStorageCredentialMonikerKey()) + configRules = append(configRules, rules.AzureStorageCredentialServiceBus()) + configRules = append(configRules, rules.AzureStorageCredentialSig53()) + configRules = append(configRules, rules.AzureStorageCredentialUserIDPW()) + configRules = append(configRules, rules.AzureStorageCredentialXStore()) + + // Below work on Regex.com but something about the internal conversion to generateUniqueTokenRegex is breaking them + //configRules = append(configRules, rules.AzurePowershellTokenCache()) + //configRules = append(configRules, rules.AzurePasswordXMLCredential()) + //configRules = append(configRules, rules.AzurePasswordXMLValue()) + //configRules = append(configRules, rules.AzurePasswordSSISProperty()) configRules = append(configRules, rules.BitBucketClientID()) configRules = append(configRules, rules.BitBucketClientSecret()) configRules = append(configRules, rules.BittrexAccessKey()) diff --git a/cmd/generate/config/rules/ansible.go b/cmd/generate/config/rules/ansible.go new file mode 100644 index 000000000..6b616e9f8 --- /dev/null +++ b/cmd/generate/config/rules/ansible.go @@ -0,0 +1,24 @@ +package rules + +import ( + "github.com/zricethezav/gitleaks/v8/cmd/generate/secrets" + "github.com/zricethezav/gitleaks/v8/config" +) + +func AnsibleVaultToken() *config.Rule { + // define rule + r := config.Rule{ + Description: "CSCAN0270 - Found Azure Subscription Token Cache.", + RuleID: "ansible-vault-token", + SecretGroup: 1, + Regex: generateUniqueTokenRegex(`ANSIBLE_VAULT;[0-9]\.[0-9];AES256;[\r\n]+[0-9]+`), + Keywords: []string{"ANSIBLE_VAULT;", "AES256;"}, + } + + // validate + tps := []string{ + generateSampleSecret("ansible-vault-token", + "ANSIBLE_VAULT;1.0;AES256;\n" + secrets.NewSecret(numeric("32"))), + } + return validate(r, tps, nil) +} diff --git a/cmd/generate/config/rules/azure.go b/cmd/generate/config/rules/azure.go new file mode 100644 index 000000000..382a20e51 --- /dev/null +++ b/cmd/generate/config/rules/azure.go @@ -0,0 +1,444 @@ +package rules + +import ( + "github.com/zricethezav/gitleaks/v8/cmd/generate/secrets" + "github.com/zricethezav/gitleaks/v8/config" +) + +// Rules come from https://www.powershellgallery.com/packages/AzSK.AzureDevOps/0.9.8/Content/Framework%5CConfigurations%5CSVT%5CAzureDevOps%5CCredentialPatterns.xml +// Only rules with 'ContentSearchPatterns' have been used. + +// CSCAN0110, CSCAN0111, CSCAN0140, CSCAN0220 searches for generic passwords - covered elsewhere + +// CSCAN0120 searches for Twilio keys - covered in twilio.go + +// CSCAN0210 checks for Git repo credentials - covered elsewhere + +// CSCAN0230 checks for Slack tokens - covered in slack.go + +// CSCAN0250 - covered in jwt.go + + +func AzureAppServiceDeploymentSecrets() *config.Rule { + // define rule + r := config.Rule{ + Description: "CSCAN0020, CSCAN0030 - Found Azure app service deployment secrets in publish settings file.", + RuleID: "azure-app-service-deployment-secrets", + SecretGroup: 1, + Regex: generateUniqueTokenRegex(`MII[a-z0-9=_\-]{200}`), + Keywords: []string{"MII"}, + } + + // validate + tps := []string{ + generateSampleSecret("azure-app-service-deployment-secrets", + "MII" + secrets.NewSecret(alphaNumeric("200"))), + } + return validate(r, tps, nil) +} + +func AzureStorageCredential86char() *config.Rule { + // define rule + r := config.Rule{ + Description: "CSCAN0030, CSCAN0090, CSCAN0150 - Found Azure storage credential in source code file.", + RuleID: "azure-storage-credential-86char", + SecretGroup: 1, + Regex: generateUniqueTokenRegex(`[ \t]{0,10}[a-zA-Z0-9/+]{86}==`), + } + + // validate + tps := []string{ + generateSampleSecret("azure-storage-credential-86char", + secrets.NewSecret(alphaNumeric("86") + "==")), + } + return validate(r, tps, nil) +} + +func AzureStorageCredential43char() *config.Rule { + // define rule + r := config.Rule{ + Description: "CSCAN0030, CSCAN0090, CSCAN0150 - Found Azure storage credential in source code file.", + RuleID: "azure-storage-credential-43char", + SecretGroup: 1, + Regex: generateUniqueTokenRegex(`[a-zA-Z0-9/+]{43}=[^{@\d%]`), + } + + // validate + tps := []string{ + generateSampleSecret("azure-storage-credential-43char", + secrets.NewSecret(alphaNumeric("43") + "=a")), + } + return validate(r, tps, nil) +} + +func AzureStorageCredentialSig53() *config.Rule { + // define rule + r := config.Rule{ + Description: "CSCAN0030, CSCAN0090, CSCAN0150 - Found Azure storage credential in source code file.", + RuleID: "azure-storage-credential-sig53", + SecretGroup: 1, + Regex: generateUniqueTokenRegex(`((sig|sas|password)=|>)[a-zA-Z0-9%]{43,53}%3d[^{a-zA-Z0-9%]`), + } + + // validate + tps := []string{ + generateSampleSecret("azure-storage-credential-sig53", + "sig=" + secrets.NewSecret(alphaNumeric("53") + "%3D")), + } + return validate(r, tps, nil) +} + + +func AzureStorageCredentialUserIDPW() *config.Rule { + // define rule + r := config.Rule{ + Description: "CSCAN0030 - Found Azure storage credential in source code file.", + RuleID: "azure-storage-credential-useridpw", + SecretGroup: 1, + Regex: generateUniqueTokenRegex(`((user) ?(id|name)|uid)=.{2,128}?\s*?;\s*?((password)|(pwd))=[^'$%>@'";\[\{][^;"']{2,350}?(;|"|')`), + } + + // validate + tps := []string{ + generateSampleSecret("azure-storage-credential-useridpw", + "userid=" + secrets.NewSecret(alphaNumeric("128")) + ";password=" + secrets.NewSecret(alphaNumeric("200")) + ";"), + } + return validate(r, tps, nil) +} + +func AzureStorageCredentialAccountKey() *config.Rule { + // define rule + r := config.Rule{ + Description: "CSCAN0030 - Found Azure storage credential in source code file.", + RuleID: "azure-storage-credential-accountkey", + SecretGroup: 1, + Regex: generateUniqueTokenRegex(`AccountKey\s*=\s*MII[a-zA-Z0-9/+]{43,}?={0,2}`), + } + + // validate + tps := []string{ + generateSampleSecret("azure-storage-credential-accountkey", + "AccountKey = MII" + secrets.NewSecret(alphaNumeric("43") + "=")), + } + return validate(r, tps, nil) +} + +func AzureStorageCredentialXStore() *config.Rule { + // define rule + r := config.Rule{ + Description: "CSCAN0100 - Found Azure storage credential in source code file.", + RuleID: "azure-storage-credential-xstore", + SecretGroup: 1, + Regex: generateUniqueTokenRegex(`["), + } + return validate(r, tps, nil) +} + +func AzureStorageCredentialServiceBus() *config.Rule { + // define rule + r := config.Rule{ + Description: "CSCAN0100 - Found Azure storage credential in source code file.", + RuleID: "azure-storage-credential-servicebus", + SecretGroup: 1, + Regex: generateUniqueTokenRegex(`["), + } + return validate(r, tps, nil) +} + +func AzureStorageCredentialMonikerKey() *config.Rule { + // define rule + r := config.Rule{ + Description: "CSCAN0130 - Found Azure storage credential in MonitoringAgent config file.", + RuleID: "azure-storage-credential-monikerkey", + SecretGroup: 1, + Regex: generateUniqueTokenRegex(`Account moniker\s?=.*key\s?=.*`), + } + + // validate + tps := []string{ + generateSampleSecret("azure-storage-credential-monikerkey", + "Account Moniker = 'John Doe' Key = '" + secrets.NewSecret(alphaNumeric("200") + "'")), + } + return validate(r, tps, nil) +} + + +func AzureStorageCredentialBlobURL() *config.Rule { + // define rule + r := config.Rule{ + Description: "CSCAN0110 - Found Azure storage credential in source code file.", + RuleID: "azure-storage-credential-bloburl", + SecretGroup: 1, + Regex: generateUniqueTokenRegex(`(?i)https://[a-zA-Z0-9-]+.(blob|file|queue|table|dfs|z8.web).core.windows.net/.*?sig=[a-zA-Z0-9%]{30,}`), + } + + // validate + tps := []string{ + generateSampleSecret("azure-storage-credential-bloburl", + "https://myacct.blob.core.windows.net/a?sp=r&sr=b&sig=" + secrets.NewSecret(alphaNumeric("43"))), + } + return validate(r, tps, nil) +} + +// CSCAN0050, CSCAN0060, CSCAN0070 - covered in PrivateKey.go + +// CSCAN0080 looks for 'Password' in XML file + +func AzurePasswordDecryptionkey() *config.Rule { + // define rule + r := config.Rule{ + Description: "CSCAN0090 - Found Azure password, symmetric key or storage credential in source file.", + RuleID: "azure-password-machinekey", + SecretGroup: 1, + Regex: generateUniqueTokenRegex(`(decryptionKey\s*\=\s*['"].*['"]|validationKey\s*\=\s*['"].*['"])`), + } + + // validate + tps := []string{ + generateSampleSecret("azure-password-machinekey", + ""), + } + return validate(r, tps, nil) +} + + +func AzurePasswordAddKey() *config.Rule { + // define rule + r := config.Rule{ + Description: "CSCAN0090 - Found Azure password, symmetric key or storage credential in source file.", + RuleID: "azure-password-addkey", + SecretGroup: 1, + Regex: generateUniqueTokenRegex(`[")), + } + return validate(r, tps, nil) +} + +func AzurePasswordConnString() *config.Rule { + // define rule + r := config.Rule{ + Description: "CSCAN0090 - Found Azure password, symmetric key or storage credential in source file.", + RuleID: "azure-password-connstring", + SecretGroup: 1, + Regex: generateUniqueTokenRegex(`(connectionstring|connstring)[^=]*?=["'][^"']*?(password)=[^\$\s;][^"'\s]*?(;|['"])`), + } + + // validate + tps := []string{ + generateSampleSecret("azure-password-connstring", + //connstring='password=secret123;Server=localhost;' + "connstring='Server=localhost;password=" + secrets.NewSecret(alphaNumeric("23") + "'")), + } + return validate(r, tps, nil) +} + +func AzurePasswordValueString() *config.Rule { + // define rule + r := config.Rule{ + Description: "CSCAN0090 - Found Azure password, symmetric key or storage credential in source file.", + RuleID: "azure-password-value-string", + SecretGroup: 1, + Regex: generateUniqueTokenRegex(`value\s?=\s?['"]((([A-Za-z0-9+/]){4}){1,200})==['"]`), + } + + // validate + tps := []string{ + generateSampleSecret("azure-password-value-string", + "Value='" + secrets.NewSecret(alphaNumeric("20") + "=='")), + } + return validate(r, tps, nil) +} + +func AzurePassworduidpw() *config.Rule { + // define rule + r := config.Rule{ + Description: "CSCAN0090, CSCAN0150 - Found Azure password, symmetric key or storage credential in source file.", + RuleID: "azure-password-uidpw", + SecretGroup: 1, + Regex: generateUniqueTokenRegex(`((user) ?(id|name)|uid)=.{2,128}?\s*?;\s*?((password|(pwd))=[^'$%@'";\[\{][^;"']{2,350}?(;|"|'))`), + } + + // validate + tps := []string{ + generateSampleSecret("azure-password-uidpw", + `uid=testuser;pwd=` + secrets.NewSecret(alphaNumeric("86") + ";")), + } + return validate(r, tps, nil) +} + +// TODO: Come back to the two XML passwords below +// func AzurePasswordXMLCredential() *config.Rule { +// // define rule +// r := config.Rule{ +// Description: "CSCAN0090, CSCAN0150 - Found Azure password, symmetric key or storage credential in source file.", +// RuleID: "azure-password-xml-credential", +// SecretGroup: 1, +// Regex: generateUniqueTokenRegex(`\s?name=['"][^"]*(key(s|[0-9])?|credential(s)?|secret(s|[0-9])?|password|token|key(primary|secondary|orsas|encrypted))['"](\s*value\s*=['"][^"]+['"].*?)`), +// } + +// // validate +// tps := []string{ +// generateSampleSecret("azure-password-xml-credential", +// "name='primary_key' value='" + secrets.NewSecret(alphaNumeric("86") + "'")), +// } +// return validate(r, tps, nil) +// } + +// func AzurePasswordXMLValue() *config.Rule { +// // define rule +// r := config.Rule{ +// Description: "CSCAN0090, CSCAN0150 - Found Azure password, symmetric key or storage credential in source file.", +// RuleID: "azure-password-xml-value", +// SecretGroup: 1, +// Regex: generateUniqueTokenRegex(`.*.+`), +// } + +// // validate +// tps := []string{ +// generateSampleSecret("azure-password-xml-value", +// //testpassword123 +// "" + secrets.NewSecret(alphaNumeric("86") + "")), +// } +// return validate(r, tps, nil) +// } + +// func AzurePasswordSSISProperty() *config.Rule { +// // define rule +// r := config.Rule{ +// Description: "CSCAN0090 - Found Azure password, symmetric key or storage credential in source file.", +// RuleID: "azure-password-ssis", +// SecretGroup: 1, +// Regex: generateUniqueTokenRegex(`(?s).*?[^><#$\[\{\(]+`), +// } + +// // validate +// tps := []string{ +// generateSampleSecret("azure-password-ssis", +// ` +// This is a random text string that contains some characters> +// ` + secrets.NewSecret(alphaNumeric("86") + "==")), +// } +// return validate(r, tps, nil) +// } + + +func AzureNetworkCredential() *config.Rule { + // define rule + r := config.Rule{ + Description: "CSCAN0160 - Found Azure domain credential in source file.", + RuleID: "azure-network-credential", + SecretGroup: 1, + Regex: generateUniqueTokenRegex(`NetworkCredential\((\s*).*,(\s*).*,(\s*)(corp|europe|middleeast|northamerica|southpacific|southamerica|fareast|africa|redmond|exchange|extranet|partners|extranettest|parttest|noe|ntdev|ntwksta|sys-wingroup|windeploy|wingroup|winse|segroup|xcorp|xrep|phx|gme|usme|cdocidm|mslpa)\)`), + } + + // validate + tps := []string{ + generateSampleSecret("azure-network-credential", + "NetworkCredential(username, password, europe)"), + } + return validate(r, tps, nil) +} + +func AzureNetworkCredentialSchtasks() *config.Rule { + // define rule + r := config.Rule{ + Description: "CSCAN0160 - Found Azure domain credential in source file.", + RuleID: "azure-network-credential-schtasks", + SecretGroup: 1, + Regex: generateUniqueTokenRegex(`schtasks.*/ru\s(corp|europe|middleeast|northamerica|southpacific|southamerica|fareast|africa|redmond|exchange|extranet|partners|extranettest|parttest|noe|ntdev|ntwksta|sys\-wingroup|windeploy|wingroup|winse|segroup|xcorp|xrep|phx|gme|usme|cdocidm|mslpa).*/rp.*`), + } + + // validate + tps := []string{ + generateSampleSecret("azure-network-credential-schtasks", + `Schtasks /create /tn corp-daily-backup /tr \corp\backup.bat /ru corp\admin /rp password /sc daily`), + } + return validate(r, tps, nil) +} + +func AzureNetworkCredentialDotNet() *config.Rule { + // define rule + r := config.Rule{ + Description: "CSCAN0160 - Found Azure domain credential in source file.", + RuleID: "azure-network-credential-dotnet", + SecretGroup: 1, + Regex: generateUniqueTokenRegex(`new-object\s*System.Net.NetworkCredential\(.*?,\s*['"][^"]+['"]`), + } + + // validate + tps := []string{ + generateSampleSecret("azure-network-credential-dotnet", + "New-Object System.Net.NetworkCredential(username, '" + secrets.NewSecret(alphaNumeric("86")) + "')"), + } + return validate(r, tps, nil) +} + +func AzureDevTFVCSecrets() *config.Rule { + // define rule + r := config.Rule{ + Description: "CSCAN0200 - Found Azure DevDiv TFVC repo secrets.", + RuleID: "azure-devtfvc-secrets", + SecretGroup: 1, + Regex: generateUniqueTokenRegex(`enc_username=.+[\n\r\s]+enc_password=.{3,}`), + } + + // validate + tps := []string{ + generateSampleSecret("azure-devtfvc-secrets", + "enc_username=myusername enc_password=" + secrets.NewSecret(alphaNumeric("86"))), + } + return validate(r, tps, nil) +} + +func AzureDevopsPAT() *config.Rule { + // define rule + r := config.Rule{ + Description: "CSCAN0240 - Found Azure Devops personal access token in source file.", + RuleID: "azure-devops-pat", + SecretGroup: 1, + Regex: generateUniqueTokenRegex(`(access_token).*?['="][a-zA-Z0-9/+]{10,99}['"]`), + } + + // validate + tps := []string{ + generateSampleSecret("azure-devops-pat", + "Access_token=='" + secrets.NewSecret(hex("52")) + "'"), + } + return validate(r, tps, nil) +} + + +// func AzurePowershellTokenCache() *config.Rule { +// // define rule +// r := config.Rule{ +// Description: "CSCAN0270 - Found Azure Subscription Token Cache.", +// RuleID: "azure-powershell-tokencache", +// SecretGroup: 1, +// // Below finds the example on Regex101.com! So not sure what's happening here. +// Regex: generateUniqueTokenRegex(`["']TokenCache["']\s*:\s*\{\s*["']CacheData["']\s*:\s*["'][a-zA-Z0-9/\+]{86}`), +// } + +// // validate +// tps := []string{ +// generateSampleSecret("azure-powershell-tokencache", +// "'TokenCache': { 'CacheData': '" + secrets.NewSecret(alphaNumeric("86")) + "'"), +// } +// return validate(r, tps, nil) +// } diff --git a/config/gitleaks.toml b/config/gitleaks.toml index 7a7f00da8..ed1bbbe82 100644 --- a/config/gitleaks.toml +++ b/config/gitleaks.toml @@ -88,6 +88,15 @@ keywords = [ "alibaba", ] +[[rules]] +description = "CSCAN0270 - Found Azure Subscription Token Cache." +id = "ansible-vault-token" +regex = '''(?i)\b(ANSIBLE_VAULT;[0-9]\.[0-9];AES256;[\r\n]+[0-9]+)(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "ansible_vault;","aes256;", +] + [[rules]] description = "Asana Client ID" id = "asana-client-id" @@ -123,6 +132,186 @@ keywords = [ "akia","agpa","aida","aroa","aipa","anpa","anva","asia", ] +[[rules]] +description = "CSCAN0020, CSCAN0030 - Found Azure app service deployment secrets in publish settings file." +id = "azure-app-service-deployment-secrets" +regex = '''(?i)\b(MII[a-z0-9=_\-]{200})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "mii", +] + +[[rules]] +description = "CSCAN0240 - Found Azure Devops personal access token in source file." +id = "azure-devops-pat" +regex = '''(?i)\b((access_token).*?['="][a-zA-Z0-9/+]{10,99}['"])(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + +] + +[[rules]] +description = "CSCAN0200 - Found Azure DevDiv TFVC repo secrets." +id = "azure-devtfvc-secrets" +regex = '''(?i)\b(enc_username=.+[\n\r\s]+enc_password=.{3,})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + +] + +[[rules]] +description = "CSCAN0160 - Found Azure domain credential in source file." +id = "azure-network-credential" +regex = '''(?i)\b(NetworkCredential\((\s*).*,(\s*).*,(\s*)(corp|europe|middleeast|northamerica|southpacific|southamerica|fareast|africa|redmond|exchange|extranet|partners|extranettest|parttest|noe|ntdev|ntwksta|sys-wingroup|windeploy|wingroup|winse|segroup|xcorp|xrep|phx|gme|usme|cdocidm|mslpa)\))(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + +] + +[[rules]] +description = "CSCAN0160 - Found Azure domain credential in source file." +id = "azure-network-credential-dotnet" +regex = '''(?i)\b(new-object\s*System.Net.NetworkCredential\(.*?,\s*['"][^"]+['"])(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + +] + +[[rules]] +description = "CSCAN0160 - Found Azure domain credential in source file." +id = "azure-network-credential-schtasks" +regex = '''(?i)\b(schtasks.*/ru\s(corp|europe|middleeast|northamerica|southpacific|southamerica|fareast|africa|redmond|exchange|extranet|partners|extranettest|parttest|noe|ntdev|ntwksta|sys\-wingroup|windeploy|wingroup|winse|segroup|xcorp|xrep|phx|gme|usme|cdocidm|mslpa).*/rp.*)(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + +] + +[[rules]] +description = "CSCAN0090 - Found Azure password, symmetric key or storage credential in source file." +id = "azure-password-addkey" +regex = '''(?i)\b([)[a-zA-Z0-9%]{43,53}%3d[^{a-zA-Z0-9%])(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + +] + +[[rules]] +description = "CSCAN0030 - Found Azure storage credential in source code file." +id = "azure-storage-credential-useridpw" +regex = '''(?i)\b(((user) ?(id|name)|uid)=.{2,128}?\s*?;\s*?((password)|(pwd))=[^'$%>@'";\[\{][^;"']{2,350}?(;|"|'))(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + +] + +[[rules]] +description = "CSCAN0100 - Found Azure storage credential in source code file." +id = "azure-storage-credential-xstore" +regex = '''(?i)\b([