From 7a85962a0db6e4c3a7ee02df5b64597fde7b2e49 Mon Sep 17 00:00:00 2001 From: Nick Hibberd Date: Mon, 10 Dec 2018 13:48:59 -0800 Subject: [PATCH 1/4] Add basic system:anonymous testing --- src/modules/hunting/apiserver.py | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/src/modules/hunting/apiserver.py b/src/modules/hunting/apiserver.py index 524eed6..e621915 100644 --- a/src/modules/hunting/apiserver.py +++ b/src/modules/hunting/apiserver.py @@ -353,6 +353,31 @@ class AccessApiServerViaServiceAccountToken(Hunter): self.publish_event(ApiServerPassiveHunterFinished(self.all_namespaces_names_evidence, self.service_account_token_evidence, self.event.host, self.event.port)) + else: + logging.debug('No service account token found, verifiying anonymous access.') + if self.get_all_namespaces(): + self.publish_event(ListAllNamespaces(self.all_namespaces_names_evidence)) + + if self.get_pods_list_under_requested_scope(): + self.publish_event(ListPodUnderAllNamespaces(self.namespaces_and_their_pod_names)) + else: + if self.get_pods_list_under_requested_scope(scope='namespaces/default'): + self.publish_event(ListPodUnderDefaultNamespace(self.namespaces_and_their_pod_names)) + + if self.get_all_roles(): + self.publish_event(ListAllRoles(self.all_roles_names_evidence)) + else: + if self.get_roles_under_default_namespace(): + self.publish_event(ListAllRolesUnderDefaultNamespace( + self.roles_names_under_default_namespace_evidence)) + if self.get_all_cluster_roles(): + self.publish_event(ListAllClusterRoles(self.all_cluster_roles_names_evidence)) + + # At this point we know we got the service_account_token, and we might got all of the namespaces + self.publish_event(ApiServerPassiveHunterFinished(self.all_namespaces_names_evidence, + self.service_account_token_evidence, + self.event.host, self.event.port)) + # Active Hunter @@ -395,8 +420,8 @@ class AccessApiServerViaServiceAccountTokenActive(ActiveHunter): privileged_value = ',"securityContext":{"privileged":true}' if is_privileged else '' json_pod = \ """ - - {{"apiVersion": "v1", + + {{"apiVersion": "v1", "kind": "Pod", "metadata": {{ "name": "{random_str}" @@ -416,7 +441,7 @@ class AccessApiServerViaServiceAccountTokenActive(ActiveHunter): ] }} }} - + """.format(random_str=(str(uuid.uuid4()))[0:5], is_privileged_flag=privileged_value) headers = { 'Content-Type': 'application/json', From eb462086e019bf984e0c70404b2582531a28fc54 Mon Sep 17 00:00:00 2001 From: Nick Hibberd Date: Sun, 6 Jan 2019 16:53:23 -0800 Subject: [PATCH 2/4] Only guard 'publish_event(ServiceAccountTokenAccess(..))' with needing the service account --- src/modules/hunting/apiserver.py | 62 ++++++++++---------------------- 1 file changed, 19 insertions(+), 43 deletions(-) diff --git a/src/modules/hunting/apiserver.py b/src/modules/hunting/apiserver.py index e621915..c1b6f2c 100644 --- a/src/modules/hunting/apiserver.py +++ b/src/modules/hunting/apiserver.py @@ -328,56 +328,32 @@ class AccessApiServerViaServiceAccountToken(Hunter): if self.get_service_account_token(): self.publish_event(ServiceAccountTokenAccess(self.service_account_token_evidence)) - if self.access_api_server(): - self.publish_event(ServerApiAccess(self.api_server_evidence)) - if self.get_all_namespaces(): - self.publish_event(ListAllNamespaces(self.all_namespaces_names_evidence)) + if self.access_api_server(): + self.publish_event(ServerApiAccess(self.api_server_evidence)) - if self.get_pods_list_under_requested_scope(): - self.publish_event(ListPodUnderAllNamespaces(self.namespaces_and_their_pod_names)) - else: - if self.get_pods_list_under_requested_scope(scope='namespaces/default'): - self.publish_event(ListPodUnderDefaultNamespace(self.namespaces_and_their_pod_names)) + if self.get_all_namespaces(): + self.publish_event(ListAllNamespaces(self.all_namespaces_names_evidence)) - if self.get_all_roles(): - self.publish_event(ListAllRoles(self.all_roles_names_evidence)) - else: - if self.get_roles_under_default_namespace(): - self.publish_event(ListAllRolesUnderDefaultNamespace( - self.roles_names_under_default_namespace_evidence)) - if self.get_all_cluster_roles(): - self.publish_event(ListAllClusterRoles(self.all_cluster_roles_names_evidence)) - - # At this point we know we got the service_account_token, and we might got all of the namespaces - self.publish_event(ApiServerPassiveHunterFinished(self.all_namespaces_names_evidence, - self.service_account_token_evidence, - self.event.host, self.event.port)) + if self.get_pods_list_under_requested_scope(): + self.publish_event(ListPodUnderAllNamespaces(self.namespaces_and_their_pod_names)) else: - logging.debug('No service account token found, verifiying anonymous access.') - if self.get_all_namespaces(): - self.publish_event(ListAllNamespaces(self.all_namespaces_names_evidence)) + if self.get_pods_list_under_requested_scope(scope='namespaces/default'): + self.publish_event(ListPodUnderDefaultNamespace(self.namespaces_and_their_pod_names)) - if self.get_pods_list_under_requested_scope(): - self.publish_event(ListPodUnderAllNamespaces(self.namespaces_and_their_pod_names)) - else: - if self.get_pods_list_under_requested_scope(scope='namespaces/default'): - self.publish_event(ListPodUnderDefaultNamespace(self.namespaces_and_their_pod_names)) - - if self.get_all_roles(): - self.publish_event(ListAllRoles(self.all_roles_names_evidence)) - else: - if self.get_roles_under_default_namespace(): - self.publish_event(ListAllRolesUnderDefaultNamespace( + if self.get_all_roles(): + self.publish_event(ListAllRoles(self.all_roles_names_evidence)) + else: + if self.get_roles_under_default_namespace(): + self.publish_event(ListAllRolesUnderDefaultNamespace( self.roles_names_under_default_namespace_evidence)) - if self.get_all_cluster_roles(): - self.publish_event(ListAllClusterRoles(self.all_cluster_roles_names_evidence)) - - # At this point we know we got the service_account_token, and we might got all of the namespaces - self.publish_event(ApiServerPassiveHunterFinished(self.all_namespaces_names_evidence, - self.service_account_token_evidence, - self.event.host, self.event.port)) + if self.get_all_cluster_roles(): + self.publish_event(ListAllClusterRoles(self.all_cluster_roles_names_evidence)) + # At this point we know we got the service_account_token, and we might got all of the namespaces + self.publish_event(ApiServerPassiveHunterFinished(self.all_namespaces_names_evidence, + self.service_account_token_evidence, + self.event.host, self.event.port)) # Active Hunter From 985d76f8a6b569c8dc995cd96a230c5b6bca4787 Mon Sep 17 00:00:00 2001 From: Liz Rice Date: Thu, 17 Jan 2019 15:51:40 +0000 Subject: [PATCH 3/4] Recent change moved service account token access Should've really been part of merge --- src/modules/hunting/apiserver.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/modules/hunting/apiserver.py b/src/modules/hunting/apiserver.py index 54a66a0..6e4b49d 100644 --- a/src/modules/hunting/apiserver.py +++ b/src/modules/hunting/apiserver.py @@ -317,8 +317,7 @@ class AccessApiServerViaServiceAccountToken(Hunter): def execute(self): - if self.get_service_account_token(): - self.publish_event(ServiceAccountTokenAccess(self.service_account_token_evidence)) + self.get_service_account_token(): if self.access_api_server(): self.publish_event(ServerApiAccess(self.api_server_evidence)) From 9b3529db0c157bda01e39c6c4a761f7b99ec3f96 Mon Sep 17 00:00:00 2001 From: Liz Rice Date: Thu, 17 Jan 2019 16:05:47 +0000 Subject: [PATCH 4/4] D'oh --- src/modules/hunting/apiserver.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/hunting/apiserver.py b/src/modules/hunting/apiserver.py index 6e4b49d..b8de74b 100644 --- a/src/modules/hunting/apiserver.py +++ b/src/modules/hunting/apiserver.py @@ -317,7 +317,7 @@ class AccessApiServerViaServiceAccountToken(Hunter): def execute(self): - self.get_service_account_token(): + self.get_service_account_token() if self.access_api_server(): self.publish_event(ServerApiAccess(self.api_server_evidence))