From 564fd1c11b124f4b17e45b0176a3120f28c89045 Mon Sep 17 00:00:00 2001 From: Johannes Feichtner Date: Wed, 27 Apr 2022 23:33:06 +0200 Subject: [PATCH] feat(query): add new k8s rule to detect account impersonation (RBAC) --- .../metadata.json | 10 ++++++++ .../query.rego | 22 ++++++++++++++++++ .../test/negative.yaml | 23 +++++++++++++++++++ .../test/positive.yaml | 23 +++++++++++++++++++ .../test/positive_expected_result.json | 7 ++++++ 5 files changed, 85 insertions(+) create mode 100644 assets/queries/k8s/rbac_roles_with_impersonate_permission/metadata.json create mode 100644 assets/queries/k8s/rbac_roles_with_impersonate_permission/query.rego create mode 100644 assets/queries/k8s/rbac_roles_with_impersonate_permission/test/negative.yaml create mode 100644 assets/queries/k8s/rbac_roles_with_impersonate_permission/test/positive.yaml create mode 100644 assets/queries/k8s/rbac_roles_with_impersonate_permission/test/positive_expected_result.json diff --git a/assets/queries/k8s/rbac_roles_with_impersonate_permission/metadata.json b/assets/queries/k8s/rbac_roles_with_impersonate_permission/metadata.json new file mode 100644 index 00000000000..4000152bfd6 --- /dev/null +++ b/assets/queries/k8s/rbac_roles_with_impersonate_permission/metadata.json @@ -0,0 +1,10 @@ +{ + "id": "9f85c3f6-26fd-4007-938a-2e0cb0100980", + "queryName": "RBAC Roles with Impersonate Permission", + "severity": "MEDIUM", + "category": "Access Control", + "descriptionText": "Roles or ClusterRoles with the permission 'impersonate' allow subjects to assume the rights of other users, groups, or service accounts. In case of compromise, attackers may abuse this sudo-like functionality to achieve privilege escalation", + "descriptionUrl": "https://kubernetes.io/docs/reference/access-authn-authz/authentication/#user-impersonation", + "platform": "Kubernetes", + "descriptionID": "9f85c3f6" +} diff --git a/assets/queries/k8s/rbac_roles_with_impersonate_permission/query.rego b/assets/queries/k8s/rbac_roles_with_impersonate_permission/query.rego new file mode 100644 index 00000000000..17b3b2f8423 --- /dev/null +++ b/assets/queries/k8s/rbac_roles_with_impersonate_permission/query.rego @@ -0,0 +1,22 @@ +package Cx + +import data.generic.common as common_lib + +CxPolicy[result] { + document := input.document[i] + metadata := document.metadata + + kinds := {"Role", "ClusterRole"} + document.kind == kinds[_] + + document.rules[j].verbs[_] == "impersonate" + + result := { + "documentId": document.id, + "searchKey": sprintf("metadata.name={{%s}}.rules", [metadata.name]), + "issueType": "IncorrectValue", + "keyExpectedValue": sprintf("metadata.name={{%s}}.rules[%d].verbs should not include the 'impersonate' verb", [metadata.name, j]), + "keyActualValue": sprintf("metadata.name={{%s}}.rules[%d].verbs includes the 'impersonate' verb", [metadata.name, j]), + "searchLine": common_lib.build_search_line(["rules", j], ["verbs"]) + } +} diff --git a/assets/queries/k8s/rbac_roles_with_impersonate_permission/test/negative.yaml b/assets/queries/k8s/rbac_roles_with_impersonate_permission/test/negative.yaml new file mode 100644 index 00000000000..06220e6e623 --- /dev/null +++ b/assets/queries/k8s/rbac_roles_with_impersonate_permission/test/negative.yaml @@ -0,0 +1,23 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: impersonator-role-neg + namespace: default +rules: +- apiGroups: [""] + resources: ["users", "groups", "serviceaccounts"] + verbs: ["get"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: rbac-impersonate-binding +subjects: +- kind: ServiceAccount + name: impersonator-sa-neg + namespace: default + apiGroup: "" +roleRef: + kind: ClusterRole + name: impersonator-role-neg + apiGroup: "" diff --git a/assets/queries/k8s/rbac_roles_with_impersonate_permission/test/positive.yaml b/assets/queries/k8s/rbac_roles_with_impersonate_permission/test/positive.yaml new file mode 100644 index 00000000000..27288554433 --- /dev/null +++ b/assets/queries/k8s/rbac_roles_with_impersonate_permission/test/positive.yaml @@ -0,0 +1,23 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: impersonator-role + namespace: default +rules: +- apiGroups: [""] + resources: ["users", "groups", "serviceaccounts"] + verbs: ["impersonate"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: rbac-impersonate-binding +subjects: +- kind: ServiceAccount + name: impersonator-sa + namespace: default + apiGroup: "" +roleRef: + kind: ClusterRole + name: impersonator-role + apiGroup: "" diff --git a/assets/queries/k8s/rbac_roles_with_impersonate_permission/test/positive_expected_result.json b/assets/queries/k8s/rbac_roles_with_impersonate_permission/test/positive_expected_result.json new file mode 100644 index 00000000000..6e71882dfd1 --- /dev/null +++ b/assets/queries/k8s/rbac_roles_with_impersonate_permission/test/positive_expected_result.json @@ -0,0 +1,7 @@ +[ + { + "queryName": "RBAC Roles with Impersonate Permission", + "severity": "MEDIUM", + "line": 9 + } +]