From 9ccea934d0fc45e26256bc3291dc1114b8ef4638 Mon Sep 17 00:00:00 2001 From: bcpenta Date: Tue, 22 Oct 2024 23:47:15 -0400 Subject: [PATCH 1/3] EKS Anonymous API Access Detection Rule --- rules/aws_eks_rules/anonymous_api_access.py | 30 +++++ rules/aws_eks_rules/anonymous_api_access.yml | 115 +++++++++++++++++++ 2 files changed, 145 insertions(+) create mode 100644 rules/aws_eks_rules/anonymous_api_access.py create mode 100644 rules/aws_eks_rules/anonymous_api_access.yml diff --git a/rules/aws_eks_rules/anonymous_api_access.py b/rules/aws_eks_rules/anonymous_api_access.py new file mode 100644 index 000000000..95b164034 --- /dev/null +++ b/rules/aws_eks_rules/anonymous_api_access.py @@ -0,0 +1,30 @@ +from panther_aws_helpers import eks_panther_obj_ref + +# Rule to detect anonymous API requests to the Kubernetes API server in EKS +def rule(event): + # Check if the username is set to "system:anonymous", which indicates anonymous access + p_eks = eks_panther_obj_ref(event) + if p_eks.get("actor") == "system:anonymous": + return True + return False + +# Custom title for alerts generated by this rule +def title(event): + p_eks = eks_panther_obj_ref(event) + return ( + f"Anonymous API access detected on Kubernetes API server " + f"from [{p_eks.get('sourceIPs')[0]}] to [{p_eks.get('resource')}] " + f"in namespace [{p_eks.get('ns')}] on [{p_eks.get('p_source_label')}]" + ) + +# Deduplication logic for grouping alerts +def dedup(event): + p_eks = eks_panther_obj_ref(event) + return f"anonymous_access_{p_eks.get('p_source_label')}_{p_eks.get('sourceIPs')[0]}" + +# Additional context for alerting +def alert_context(event): + p_eks = eks_panther_obj_ref(event) + mutable_event = event.to_dict() + mutable_event["p_eks"] = p_eks + return dict(mutable_event) diff --git a/rules/aws_eks_rules/anonymous_api_access.yml b/rules/aws_eks_rules/anonymous_api_access.yml new file mode 100644 index 000000000..85ca82f7c --- /dev/null +++ b/rules/aws_eks_rules/anonymous_api_access.yml @@ -0,0 +1,115 @@ +AnalysisType: rule +Filename: anonymous_api_access.py +RuleID: "Amazon.EKS.AnonymousAPIAccess" +DisplayName: "EKS Anonymous API Access Detected" +Enabled: true +LogTypes: + - Amazon.EKS.Audit +Tags: + - EKS + - Security Control + - API +Reports: + MITRE ATT&CK: + - "TA0001:T1190" # Initial Access: Exploit Public-Facing Application +Severity: Medium +Description: > + This rule detects anonymous API requests made to the Kubernetes API server. + In production environments, anonymous access should be disabled to prevent + unauthorized access to the API server. +Runbook: > + Check the EKS cluster configuration and ensure that anonymous access + to the Kubernetes API server is disabled. This can be done by verifying the + API server arguments and authentication webhook configuration. +Reference: https://kubernetes.io/docs/reference/access-authn-authz/authentication/#anonymous-requests +DedupPeriodMinutes: 60 +SummaryAttributes: + - user:username + - p_any_ip_addresses + - p_source_label +Tests: + - Name: Anonymous API Access + ExpectedResult: true + Log: + { + "annotations": + { + "authorization.k8s.io/decision": "allow", + "authorization.k8s.io/reason": "RBAC: allowed by ClusterRoleBinding system:public-info-viewer", + }, + "apiVersion": "audit.k8s.io/v1", + "auditID": "abcde12345", + "kind": "Event", + "level": "Request", + "objectRef": + { + "apiVersion": "v1", + "name": "test-pod", + "namespace": "default", + "resource": "pods", + }, + "p_any_aws_account_ids": ["123412341234"], + "p_any_aws_arns": [ + "arn:aws:iam::123412341234:role/DevAdministrator" + ], + "p_any_ip_addresses": ["8.8.8.8"], + "p_any_usernames": ["system:anonymous"], + "p_event_time": "2022-11-29 00:09:04.38", + "p_log_type": "Amazon.EKS.Audit", + "p_parse_time": "2022-11-29 00:10:25.067", + "p_row_id": "2e4ab474b0f0f7a4a8fff4f014a9b32a", + "p_source_id": "4c859cd4-9406-469b-9e0e-c2dc1bee24fa", + "p_source_label": "example-cluster-eks-logs", + "requestReceivedTimestamp": "2022-11-29 00:09:04.38", + "requestURI": "/api/v1/namespaces/default/pods/test-pod", + "responseStatus": { "code": 200 }, + "sourceIPs": ["8.8.8.8"], + "stage": "ResponseComplete", + "user": { + "username": "system:anonymous" + }, + "userAgent": "kubectl/v1.25.4" + } + + - Name: Non-Anonymous API Access + ExpectedResult: false + Log: + { + "annotations": + { + "authorization.k8s.io/decision": "allow", + "authorization.k8s.io/reason": "RBAC: allowed by ClusterRoleBinding system:public-info-viewer", + }, + "apiVersion": "audit.k8s.io/v1", + "auditID": "abcde12345", + "kind": "Event", + "level": "Request", + "objectRef": + { + "apiVersion": "v1", + "name": "test-pod", + "namespace": "default", + "resource": "pods", + }, + "p_any_aws_account_ids": ["123412341234"], + "p_any_aws_arns": [ + "arn:aws:iam::123412341234:role/DevAdministrator" + ], + "p_any_ip_addresses": ["8.8.8.8"], + "p_any_usernames": ["kubernetes-admin"], + "p_event_time": "2022-11-29 00:09:04.38", + "p_log_type": "Amazon.EKS.Audit", + "p_parse_time": "2022-11-29 00:10:25.067", + "p_row_id": "2e4ab474b0f0f7a4a8fff4f014a9b32a", + "p_source_id": "4c859cd4-9406-469b-9e0e-c2dc1bee24fa", + "p_source_label": "example-cluster-eks-logs", + "requestReceivedTimestamp": "2022-11-29 00:09:04.38", + "requestURI": "/api/v1/namespaces/default/pods/test-pod", + "responseStatus": { "code": 200 }, + "sourceIPs": ["8.8.8.8"], + "stage": "ResponseComplete", + "user": { + "username": "kubernetes-admin" + }, + "userAgent": "kubectl/v1.25.4" + } From f7c83bbbc1a99f3d6b1473ca3357620339ce854c Mon Sep 17 00:00:00 2001 From: bcpenta Date: Tue, 22 Oct 2024 23:50:12 -0400 Subject: [PATCH 2/3] EKS Anonymous API Access Detection Rule --- rules/aws_eks_rules/anonymous_api_access.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/rules/aws_eks_rules/anonymous_api_access.yml b/rules/aws_eks_rules/anonymous_api_access.yml index 85ca82f7c..dd3391dc0 100644 --- a/rules/aws_eks_rules/anonymous_api_access.yml +++ b/rules/aws_eks_rules/anonymous_api_access.yml @@ -113,3 +113,4 @@ Tests: }, "userAgent": "kubectl/v1.25.4" } + From 4461ab7fbc8454d007ec42d21cffe60eb8ef9129 Mon Sep 17 00:00:00 2001 From: Ben Airey Date: Mon, 28 Oct 2024 14:30:33 -0500 Subject: [PATCH 3/3] format changes and added to AWS pack --- packs/aws.yml | 1 + rules/aws_eks_rules/anonymous_api_access.py | 8 +- rules/aws_eks_rules/anonymous_api_access.yml | 110 +++++++++++-------- 3 files changed, 68 insertions(+), 51 deletions(-) diff --git a/packs/aws.yml b/packs/aws.yml index dac64c888..db861f0df 100644 --- a/packs/aws.yml +++ b/packs/aws.yml @@ -142,6 +142,7 @@ PackDefinition: - AWS.CMK.KeyRotation - AWS.DynamoDB.TableTTLEnabled - AWS.EC2.Vulnerable.XZ.Image.Launched + - Amazon.EKS.AnonymousAPIAccess - AWS.IAM.Policy.DoesNotGrantAdminAccess - AWS.IAM.Policy.DoesNotGrantNetworkAdminAccess - AWS.IAM.Resource.DoesNotHaveInlinePolicy diff --git a/rules/aws_eks_rules/anonymous_api_access.py b/rules/aws_eks_rules/anonymous_api_access.py index 95b164034..b85f24fde 100644 --- a/rules/aws_eks_rules/anonymous_api_access.py +++ b/rules/aws_eks_rules/anonymous_api_access.py @@ -1,6 +1,6 @@ from panther_aws_helpers import eks_panther_obj_ref -# Rule to detect anonymous API requests to the Kubernetes API server in EKS + def rule(event): # Check if the username is set to "system:anonymous", which indicates anonymous access p_eks = eks_panther_obj_ref(event) @@ -8,7 +8,7 @@ def rule(event): return True return False -# Custom title for alerts generated by this rule + def title(event): p_eks = eks_panther_obj_ref(event) return ( @@ -17,12 +17,12 @@ def title(event): f"in namespace [{p_eks.get('ns')}] on [{p_eks.get('p_source_label')}]" ) -# Deduplication logic for grouping alerts + def dedup(event): p_eks = eks_panther_obj_ref(event) return f"anonymous_access_{p_eks.get('p_source_label')}_{p_eks.get('sourceIPs')[0]}" -# Additional context for alerting + def alert_context(event): p_eks = eks_panther_obj_ref(event) mutable_event = event.to_dict() diff --git a/rules/aws_eks_rules/anonymous_api_access.yml b/rules/aws_eks_rules/anonymous_api_access.yml index dd3391dc0..e8f2548fb 100644 --- a/rules/aws_eks_rules/anonymous_api_access.yml +++ b/rules/aws_eks_rules/anonymous_api_access.yml @@ -5,55 +5,61 @@ DisplayName: "EKS Anonymous API Access Detected" Enabled: true LogTypes: - Amazon.EKS.Audit -Tags: - - EKS - - Security Control - - API +Severity: Medium Reports: MITRE ATT&CK: - "TA0001:T1190" # Initial Access: Exploit Public-Facing Application -Severity: Medium Description: > This rule detects anonymous API requests made to the Kubernetes API server. In production environments, anonymous access should be disabled to prevent unauthorized access to the API server. +DedupPeriodMinutes: 60 +Reference: + https://kubernetes.io/docs/reference/access-authn-authz/authentication/#anonymous-requests Runbook: > Check the EKS cluster configuration and ensure that anonymous access - to the Kubernetes API server is disabled. This can be done by verifying the - API server arguments and authentication webhook configuration. -Reference: https://kubernetes.io/docs/reference/access-authn-authz/authentication/#anonymous-requests -DedupPeriodMinutes: 60 + to the Kubernetes API server is disabled. This can be done by verifying the API + server arguments and authentication webhook configuration. SummaryAttributes: - user:username - p_any_ip_addresses - p_source_label +Tags: + - EKS + - Security Control + - API + - Initial Access:Exploit Public-Facing Application Tests: - Name: Anonymous API Access ExpectedResult: true Log: { - "annotations": - { - "authorization.k8s.io/decision": "allow", - "authorization.k8s.io/reason": "RBAC: allowed by ClusterRoleBinding system:public-info-viewer", - }, + "annotations": { + "authorization.k8s.io/decision": "allow", + "authorization.k8s.io/reason": "RBAC: allowed by ClusterRoleBinding system:public-info-viewer" + }, "apiVersion": "audit.k8s.io/v1", "auditID": "abcde12345", "kind": "Event", "level": "Request", - "objectRef": - { - "apiVersion": "v1", - "name": "test-pod", - "namespace": "default", - "resource": "pods", - }, - "p_any_aws_account_ids": ["123412341234"], + "objectRef": { + "apiVersion": "v1", + "name": "test-pod", + "namespace": "default", + "resource": "pods" + }, + "p_any_aws_account_ids": [ + "123412341234" + ], "p_any_aws_arns": [ - "arn:aws:iam::123412341234:role/DevAdministrator" + "arn:aws:iam::123412341234:role/DevAdministrator" + ], + "p_any_ip_addresses": [ + "8.8.8.8" + ], + "p_any_usernames": [ + "system:anonymous" ], - "p_any_ip_addresses": ["8.8.8.8"], - "p_any_usernames": ["system:anonymous"], "p_event_time": "2022-11-29 00:09:04.38", "p_log_type": "Amazon.EKS.Audit", "p_parse_time": "2022-11-29 00:10:25.067", @@ -62,41 +68,48 @@ Tests: "p_source_label": "example-cluster-eks-logs", "requestReceivedTimestamp": "2022-11-29 00:09:04.38", "requestURI": "/api/v1/namespaces/default/pods/test-pod", - "responseStatus": { "code": 200 }, - "sourceIPs": ["8.8.8.8"], + "responseStatus": { + "code": 200 + }, + "sourceIPs": [ + "8.8.8.8" + ], "stage": "ResponseComplete", "user": { "username": "system:anonymous" }, "userAgent": "kubectl/v1.25.4" } - - Name: Non-Anonymous API Access ExpectedResult: false Log: { - "annotations": - { - "authorization.k8s.io/decision": "allow", - "authorization.k8s.io/reason": "RBAC: allowed by ClusterRoleBinding system:public-info-viewer", - }, + "annotations": { + "authorization.k8s.io/decision": "allow", + "authorization.k8s.io/reason": "RBAC: allowed by ClusterRoleBinding system:public-info-viewer" + }, "apiVersion": "audit.k8s.io/v1", "auditID": "abcde12345", "kind": "Event", "level": "Request", - "objectRef": - { - "apiVersion": "v1", - "name": "test-pod", - "namespace": "default", - "resource": "pods", - }, - "p_any_aws_account_ids": ["123412341234"], + "objectRef": { + "apiVersion": "v1", + "name": "test-pod", + "namespace": "default", + "resource": "pods" + }, + "p_any_aws_account_ids": [ + "123412341234" + ], "p_any_aws_arns": [ - "arn:aws:iam::123412341234:role/DevAdministrator" + "arn:aws:iam::123412341234:role/DevAdministrator" + ], + "p_any_ip_addresses": [ + "8.8.8.8" + ], + "p_any_usernames": [ + "kubernetes-admin" ], - "p_any_ip_addresses": ["8.8.8.8"], - "p_any_usernames": ["kubernetes-admin"], "p_event_time": "2022-11-29 00:09:04.38", "p_log_type": "Amazon.EKS.Audit", "p_parse_time": "2022-11-29 00:10:25.067", @@ -105,12 +118,15 @@ Tests: "p_source_label": "example-cluster-eks-logs", "requestReceivedTimestamp": "2022-11-29 00:09:04.38", "requestURI": "/api/v1/namespaces/default/pods/test-pod", - "responseStatus": { "code": 200 }, - "sourceIPs": ["8.8.8.8"], + "responseStatus": { + "code": 200 + }, + "sourceIPs": [ + "8.8.8.8" + ], "stage": "ResponseComplete", "user": { "username": "kubernetes-admin" }, "userAgent": "kubectl/v1.25.4" } -