From fe14341544328f28de4b5fcedc67ee4d8a73d7e9 Mon Sep 17 00:00:00 2001 From: Ben Date: Thu, 25 Jan 2024 12:34:51 +0200 Subject: [PATCH] Adding control C-0265 Signed-off-by: Ben --- controls/C-0265-authenticateduserhasrbac.json | 24 ++++++ frameworks/allcontrols.json | 8 +- frameworks/clusterscan.json | 6 ++ frameworks/security.json | 12 ++- .../raw.rego | 65 ++++++++++++++++ .../rule.metadata.json | 27 +++++++ .../test/fail/expected.json | 74 +++++++++++++++++++ .../test/fail/input/clusterrole.yaml | 18 +++++ .../test/fail/input/clusterrolebinding.yaml | 12 +++ .../test/success/expected.json | 1 + .../test/success/input/rolebinding.yaml | 26 +++++++ 11 files changed, 269 insertions(+), 4 deletions(-) create mode 100644 controls/C-0265-authenticateduserhasrbac.json create mode 100644 rules/system-authenticated-allowed-to-take-over-cluster/raw.rego create mode 100644 rules/system-authenticated-allowed-to-take-over-cluster/rule.metadata.json create mode 100644 rules/system-authenticated-allowed-to-take-over-cluster/test/fail/expected.json create mode 100644 rules/system-authenticated-allowed-to-take-over-cluster/test/fail/input/clusterrole.yaml create mode 100644 rules/system-authenticated-allowed-to-take-over-cluster/test/fail/input/clusterrolebinding.yaml create mode 100644 rules/system-authenticated-allowed-to-take-over-cluster/test/success/expected.json create mode 100644 rules/system-authenticated-allowed-to-take-over-cluster/test/success/input/rolebinding.yaml diff --git a/controls/C-0265-authenticateduserhasrbac.json b/controls/C-0265-authenticateduserhasrbac.json new file mode 100644 index 000000000..1d023639e --- /dev/null +++ b/controls/C-0265-authenticateduserhasrbac.json @@ -0,0 +1,24 @@ +{ + "controlID": "C-0265", + "name": "system:authenticated user has elevated roles", + "description": "Granting permissions to the system:authenticated group is generally not recommended and can introduce security risks. This control ensures that system:authenticated users do not have cluster risking permissions.", + "remediation": "Review and modify your cluster's RBAC configuration to ensure that system:authenticated will have minimal permissions.", + "test": "Checks if ClusterRoleBinding/RoleBinding resources give permissions to system:authenticated group.", + "attributes": { + }, + "rulesNames": [ + "system-authenticated-allowed-to-take-over-cluster" + ], + "baseScore": 7, + "category": { + "name": "Control plane", + "subCategory": { + "name": "Supply chain" + } + }, + "scanningScope": { + "matches": [ + "cluster" + ] + } +} \ No newline at end of file diff --git a/frameworks/allcontrols.json b/frameworks/allcontrols.json index f8f28441c..24461d865 100644 --- a/frameworks/allcontrols.json +++ b/frameworks/allcontrols.json @@ -372,11 +372,17 @@ "name": "CVE-2022-47633-kyverno-signature-bypass" } }, - { + { "controlID": "C-0262", "patch": { "name": "Anonymous access enabled" } + }, + { + "controlID": "C-0265", + "patch": { + "name": "Authenticated user has sensitive permissions" + } } ] } diff --git a/frameworks/clusterscan.json b/frameworks/clusterscan.json index 2b805b803..1d19a251f 100644 --- a/frameworks/clusterscan.json +++ b/frameworks/clusterscan.json @@ -38,6 +38,12 @@ "name": "Anonymous access enabled" } }, + { + "controlID": "C-0265", + "patch": { + "name": "Authenticated user has sensitive permissions" + } + }, { "controlID": "C-0015", "patch": { diff --git a/frameworks/security.json b/frameworks/security.json index 23a6b2765..cf5306156 100644 --- a/frameworks/security.json +++ b/frameworks/security.json @@ -26,7 +26,7 @@ "name": "Immutable container filesystem" } }, - { + { "controlID": "C-0256", "patch": { "name": "Exposure to Internet" @@ -62,7 +62,7 @@ "name": "ServiceAccount token mounted" } }, - { + { "controlID": "C-0255", "patch": { "name": "Workload with secret access" @@ -104,11 +104,17 @@ "name": "Apply Security Context to Your Pods and Containers" } }, - { + { "controlID": "C-0262", "patch": { "name": "Anonymous access enabled" } + }, + { + "controlID": "C-0265", + "patch": { + "name": "Authenticated user has sensitive permissions" + } } ] } diff --git a/rules/system-authenticated-allowed-to-take-over-cluster/raw.rego b/rules/system-authenticated-allowed-to-take-over-cluster/raw.rego new file mode 100644 index 000000000..251abcbe2 --- /dev/null +++ b/rules/system-authenticated-allowed-to-take-over-cluster/raw.rego @@ -0,0 +1,65 @@ +package armo_builtins + +import future.keywords.in + +deny[msga] { + subjectVector := input[_] + + rolebinding := subjectVector.relatedObjects[j] + endswith(rolebinding.kind, "Binding") + + + subject := rolebinding.subjects[k] + # Check if the subject is gourp + subject.kind == "Group" + # Check if the subject is system:authenticated + subject.name == "system:authenticated" + + + # Find the bound roles + role := subjectVector.relatedObjects[i] + endswith(role.kind, "Role") + + # Check if the role and rolebinding bound + is_same_role_and_binding(role, rolebinding) + + + # Check if the role has access to workloads, exec, attach, portforward + rule := role.rules[p] + rule.resources[l] in ["*","pods", "pods/exec", "pods/attach", "pods/portforward","deployments","statefulset","daemonset","jobs","cronjobs","nodes","secrets"] + + finalpath := array.concat([""], [ + sprintf("relatedObjects[%d].subjects[%d]", [j, k]), + sprintf("relatedObjects[%d].roleRef.name", [i]), + ]) + + msga := { + "alertMessage": "system:authenticated has sensitive roles", + "alertScore": 5, + "reviewPaths": finalpath, + "failedPaths": finalpath, + "fixPaths": [], + "packagename": "armo_builtins", + "alertObject": { + "k8sApiObjects": [], + "externalObjects" : subjectVector + }, + } +} + +is_same_role_and_binding(role, rolebinding) { + rolebinding.kind == "RoleBinding" + role.kind == "Role" + rolebinding.metadata.namespace == role.metadata.namespace + rolebinding.roleRef.name == role.metadata.name + rolebinding.roleRef.kind == role.kind + startswith(role.apiVersion, rolebinding.roleRef.apiGroup) +} + +is_same_role_and_binding(role, rolebinding) { + rolebinding.kind == "ClusterRoleBinding" + role.kind == "ClusterRole" + rolebinding.roleRef.name == role.metadata.name + rolebinding.roleRef.kind == role.kind + startswith(role.apiVersion, rolebinding.roleRef.apiGroup) +} \ No newline at end of file diff --git a/rules/system-authenticated-allowed-to-take-over-cluster/rule.metadata.json b/rules/system-authenticated-allowed-to-take-over-cluster/rule.metadata.json new file mode 100644 index 000000000..37a004adc --- /dev/null +++ b/rules/system-authenticated-allowed-to-take-over-cluster/rule.metadata.json @@ -0,0 +1,27 @@ +{ + "name": "system-authenticated-allowed-to-take-over-cluster", + "attributes": { + "resourcesAggregator": "subject-role-rolebinding" + }, + "ruleLanguage": "Rego", + "match": [ + { + "apiGroups": [ + "rbac.authorization.k8s.io" + ], + "apiVersions": [ + "v1" + ], + "resources": [ + "RoleBinding", + "ClusterRoleBinding", + "Role", + "ClusterRole" + ] + } + ], + "ruleDependencies": [], + "description": "Fails in system:authenticated user has cluster takeover rbac permissions (is bound by a RoleBinding/ClusterRoleBinding)", + "remediation": "Remove any RBAC rules which allow system:authenticated users to perform actions", + "ruleQuery": "armo_builtins" +} diff --git a/rules/system-authenticated-allowed-to-take-over-cluster/test/fail/expected.json b/rules/system-authenticated-allowed-to-take-over-cluster/test/fail/expected.json new file mode 100644 index 000000000..28ad87b4f --- /dev/null +++ b/rules/system-authenticated-allowed-to-take-over-cluster/test/fail/expected.json @@ -0,0 +1,74 @@ +[ + { + "alertMessage": "system:authenticated has sensitive roles", + "alertObject": { + "externalObjects": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "Group", + "name": "system:authenticated", + "relatedObjects": [ + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "name": "system:viewer" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "system:viewer" + }, + "subjects": [ + { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "Group", + "name": "system:authenticated" + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "name": "system:viewer" + }, + "rules": [ + { + "apiGroups": [ + "" + ], + "resources": [ + "nodes", + "nodes/*", + "namespaces", + "namespaces/*", + "pods", + "pods/*" + ], + "verbs": [ + "get", + "list", + "watch" + ] + } + ] + } + ] + }, + "k8sApiObjects": [] + }, + "alertScore": 5, + "failedPaths": [ + "", + "relatedObjects[0].subjects[0]", + "relatedObjects[1].roleRef.name" + ], + "fixPaths": [], + "packagename": "armo_builtins", + "reviewPaths": [ + "", + "relatedObjects[0].subjects[0]", + "relatedObjects[1].roleRef.name" + ] + } +] \ No newline at end of file diff --git a/rules/system-authenticated-allowed-to-take-over-cluster/test/fail/input/clusterrole.yaml b/rules/system-authenticated-allowed-to-take-over-cluster/test/fail/input/clusterrole.yaml new file mode 100644 index 000000000..a374bc4be --- /dev/null +++ b/rules/system-authenticated-allowed-to-take-over-cluster/test/fail/input/clusterrole.yaml @@ -0,0 +1,18 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: system:viewer +rules: +- apiGroups: + - "" + resources: + - nodes + - nodes/* + - namespaces + - namespaces/* + - pods + - pods/* + verbs: + - get + - list + - watch \ No newline at end of file diff --git a/rules/system-authenticated-allowed-to-take-over-cluster/test/fail/input/clusterrolebinding.yaml b/rules/system-authenticated-allowed-to-take-over-cluster/test/fail/input/clusterrolebinding.yaml new file mode 100644 index 000000000..1c989e816 --- /dev/null +++ b/rules/system-authenticated-allowed-to-take-over-cluster/test/fail/input/clusterrolebinding.yaml @@ -0,0 +1,12 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: system:viewer +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: system:viewer +subjects: +- apiGroup: rbac.authorization.k8s.io + kind: Group + name: system:authenticated \ No newline at end of file diff --git a/rules/system-authenticated-allowed-to-take-over-cluster/test/success/expected.json b/rules/system-authenticated-allowed-to-take-over-cluster/test/success/expected.json new file mode 100644 index 000000000..fe51488c7 --- /dev/null +++ b/rules/system-authenticated-allowed-to-take-over-cluster/test/success/expected.json @@ -0,0 +1 @@ +[] diff --git a/rules/system-authenticated-allowed-to-take-over-cluster/test/success/input/rolebinding.yaml b/rules/system-authenticated-allowed-to-take-over-cluster/test/success/input/rolebinding.yaml new file mode 100644 index 000000000..3909d713d --- /dev/null +++ b/rules/system-authenticated-allowed-to-take-over-cluster/test/success/input/rolebinding.yaml @@ -0,0 +1,26 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: system:viewer +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: system:viewer +subjects: +- apiGroup: rbac.authorization.k8s.io + kind: Group + name: system:authenticated +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: system:viewer +rules: +- apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch \ No newline at end of file