Quellcode durchsuchen

(feat): Adding secret detection rule for Kubernetes secrets (#1454)

* (feat): Adding secret detection rule for Kubernetes secrets

Signed-off-by: localleon <me@lrau.xyz>

* (fix): Limiting kubernetes secret detection only to .yaml/.yml files

Signed-off-by: localleon <me@lrau.xyz>

* (fix): Fixing path validation testing for kubernetes-secret

Signed-off-by: localleon <me@lrau.xyz>

* (fix): refactoring path validation regex for kubernetes secret

* (fix): fixing keyword for kubernetes secret

Signed-off-by: localleon <me@lrau.xyz>

* (fix): fixing config.toml for kubernetes-secret and reording rules/main.go

Signed-off-by: localleon <me@lrau.xyz>

* (feat): Implementing proxmitiy matching for data-key in kubernetes secrets

Signed-off-by: localleon <me@lrau.xyz>

* (fix): Adding regex sugestions for quoted strings and qouted test-cases

* (fix): Updating kubernetes-secret regex to allow '-character before secret e.g if theres quoting

* limit whitespace

---------

Signed-off-by: localleon <me@lrau.xyz>
Co-authored-by: Zach <zricer@protonmail.com>
Leon vor 1 Jahr
Ursprung
Commit
7697b3e989
3 geänderte Dateien mit 88 neuen und 0 gelöschten Zeilen
  1. 2 0
      cmd/generate/config/main.go
  2. 68 0
      cmd/generate/config/rules/kubernetes.go
  3. 18 0
      config/gitleaks.toml

+ 2 - 0
cmd/generate/config/main.go

@@ -113,6 +113,8 @@ func main() {
 		rules.JWT(),
 		rules.JWTBase64(),
 		rules.KrakenAccessToken(),
+		rules.KubernetesSecretWithDataAfter(),
+		rules.KubernetesSecretWithDataBefore(),
 		rules.KucoinAccessToken(),
 		rules.KucoinSecretKey(),
 		rules.LaunchDarklyAccessToken(),

+ 68 - 0
cmd/generate/config/rules/kubernetes.go

@@ -0,0 +1,68 @@
+package rules
+
+import (
+	"regexp"
+
+	"github.com/zricethezav/gitleaks/v8/config"
+)
+
+// The kubernetes rules are split into two functions to make the complex proximity matching of the data-key and the kind-identifier more readable and testable
+
+// KubernetesSecretWithDataBefore validates if we detected a kubernetes secret which contains data, before the resource identifier!
+func KubernetesSecretWithDataBefore() *config.Rule {
+	// define rule
+	r := config.Rule{
+		RuleID:      "kubernetes-secret-with-data-before",
+		Description: "Possible Kubernetes Secret detected, posing a risk of leaking credentials/tokens from your deployments",
+		// We try to match secrets by looking if we have the keyword
+		Regex: generateUniqueTokenRegex(`(?i)(?:\b(?:data:))(\W+(?:\w+\W+){0,200}?)\bkind:.{0,10}Secret\b`, true),
+
+		Keywords: []string{
+			"Secret",
+		},
+		// Kubernetes secrets are always yaml files, we limit to common yaml-endings to make this rule more safe!
+		Path: regexp.MustCompile(`(?i)\.ya?ml$`),
+	}
+
+	// validate
+	tps := map[string]string{
+		// Sample Kubernetes Secret from https://kubernetes.io/docs/concepts/configuration/secret/
+		// These secrets contain the "data"-key before the actual identifier "kind: Secret"
+		"kubernetes.yaml": "apiVersion: v1'\n' data:'\n' extra: YmFyCg=='\n' kind: secret'\n' metadata:'\n' name: secret-sa-sample'\n' annotations:'\n' kubernetes.io/service-account.name: 'sa-name'",                                                  // gitleaks:allow
+		"kubernetes.yml":  "apiVersion: v1'\n' data:'\n' password: UyFCXCpkJHpEc2I9'\n' username: YWRtaW4='\n' kind: Secret'\n' metadata:'\n' creationTimestamp: '2022-06-28T17:44:13Z''\n' name: db-user-pass'\n' namespace: default'\n' type: Opaque", // gitleaks:allow
+		// Quoted Test Cases
+		"kubernetes-quoted-1.yaml": "apiVersion: v1'\n' data:'\n' extra: YmFyCg=='\n' kind: 'Secret''\n' metadata:'\n' name: 'secret-sa-sample''\n' annotations:'\n' kubernetes.io/service-account.name: 'sa-name'", // gitleaks:allow
+		"kubernetes-quoted-2.yaml": "apiVersion: v1'\n' data:'\n' extra: YmFyCg=='\n' kind: 'secret''\n' metadata:'\n' name: 'secret-sa-sample''\n' annotations:'\n' kubernetes.io/service-account.name: 'sa-name'", // gitleaks:allow
+	}
+	return validateWithPaths(r, tps, nil)
+}
+
+// KubernetesSecretWithDataAfter validates if we detected a kubernetes secret which contains data, after the resource identifier!
+func KubernetesSecretWithDataAfter() *config.Rule {
+	// define rule
+	r := config.Rule{
+		RuleID:      "kubernetes-secret-with-data-after",
+		Description: "Possible Kubernetes Secret detected, posing a risk of leaking credentials/tokens from your deployments",
+		// We try to match secrets by looking if we have the keyword
+		Regex: generateUniqueTokenRegex(`(?i)(?:\bkind:.{0,10}Secret\b)(?:.|\s){0,200}?\b(?:data:)\s*(.+)`, true),
+
+		Keywords: []string{
+			"Secret",
+		},
+		// Kubernetes secrets are always yaml files, we limit to common yaml-endings to make this rule more safe!
+		Path: regexp.MustCompile(`(?i)\.ya?ml$`),
+	}
+
+	// validate
+	tps := map[string]string{
+		// Sample Kubernetes Secret from https://kubernetes.io/docs/concepts/configuration/secret/
+		// These secrets contain the data after the  actual identifier "kind: Secret"
+		"kubernetes.yaml": "apiVersion: v1'\n' kind: secret'\n' data:'\n' extra: YmFyCg=='\n' metadata:'\n' name: secret-sa-sample'\n' annotations:'\n' kubernetes.io/service-account.name: 'sa-name'",                                                  // gitleaks:allow
+		"kubernetes.yml":  "apiVersion: v1'\n' kind: Secret'\n' data:'\n' password: UyFCXCpkJHpEc2I9'\n' username: YWRtaW4='\n' metadata:'\n' creationTimestamp: '2022-06-28T17:44:13Z''\n' name: db-user-pass'\n' namespace: default'\n' type: Opaque", // gitleaks:allow
+		// Quoted Test Cases
+		"kubernetes-quoted-1.yaml": "apiVersion: v1'\n' kind: 'Secret''\n' data:'\n' password: UyFCXCpkJHpEc2I9'\n' username: YWRtaW4='\n' metadata:'\n' name: db-user-pass'\n' namespace: default'\n' type: Opaque", // gitleaks:allow
+		"kubernetes-quoted-2.yaml": "apiVersion: v1'\n' kind: 'secret''\n' data:'\n' password: UyFCXCpkJHpEc2I9'\n' username: YWRtaW4='\n' metadata:'\n' name: db-user-pass'\n' namespace: default'\n' type: Opaque", // gitleaks:allow
+	}
+
+	return validateWithPaths(r, tps, nil)
+}

+ 18 - 0
config/gitleaks.toml

@@ -2216,6 +2216,24 @@ keywords = [
     "kraken",
 ]
 
+[[rules]]
+id = "kubernetes-secret-with-data-after"
+description = "Possible Kubernetes Secret detected, posing a risk of leaking credentials/tokens from your deployments"
+regex = '''(?i)\b((?i)(?:\bkind:.{0,10}Secret\b)(?:.|\s){0,200}?\b(?:data:)\s*(.+))(?:['|\"|\n|\r|\s|\x60|;]|$)'''
+path = '''(?i)\.ya?ml$'''
+keywords = [
+    "secret",
+]
+
+[[rules]]
+id = "kubernetes-secret-with-data-before"
+description = "Possible Kubernetes Secret detected, posing a risk of leaking credentials/tokens from your deployments"
+regex = '''(?i)\b((?i)(?:\b(?:data:))(\W+(?:\w+\W+){0,200}?)\bkind:.{0,10}Secret\b)(?:['|\"|\n|\r|\s|\x60|;]|$)'''
+path = '''(?i)\.ya?ml$'''
+keywords = [
+    "secret",
+]
+
 [[rules]]
 id = "kucoin-access-token"
 description = "Found a Kucoin Access Token, risking unauthorized access to cryptocurrency exchange services and transactions."