Detection rules › Panther
Panther rules: anonymous
| Rule | Severity |
|---|---|
| EKS Anonymous API Access Detected | low |
EKS Anonymous API Access Detected
#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.
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Initial Access |
Detection logic
from ipaddress import ip_address
from panther_aws_helpers import eks_panther_obj_ref
def rule(event):
src_ip = event.get("sourceIPs", ["0.0.0.0"]) # nosec
if src_ip == ["127.0.0.1"]:
return False
if event.get("userAgent", "") == "ELB-HealthChecker/2.0":
try:
if ip_address(src_ip[0]).is_private:
return False
except ValueError:
pass
# Check if the username is set to "system:anonymous", which indicates anonymous access
if event.deep_get("user", "username") == "system:anonymous":
return True
return False
def title(event):
# For INFO-level events, just group them all together since they're not that interesting
if event.deep_get("annotations", "authorization.k8s.io/decision") != "allow":
return "Failed Anonymous EKS Access Attempt(s) Detected"
if event.get("requestURI") == "/version":
return "Anonymous EKS Access to /version Endpoint Detected"
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 [{event.get('requestURI', 'NO_URI')}] "
f"on [{p_eks.get('p_source_label')}]"
)
def severity(event):
if event.deep_get("annotations", "authorization.k8s.io/decision") != "allow":
return "INFO"
if event.get("requestURI") == "/version":
return "INFO"
return "DEFAULT"
def dedup(event):
# For INFO-level events, just group them all together since they're not that interesting
if severity(event) == "INFO":
return "no dedup"
p_eks = eks_panther_obj_ref(event)
return f"anonymous_access_{p_eks.get('p_source_label')}_{event.get('userAgent')}"
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)
Rule specification
AnalysisType: rule
Filename: anonymous_api_access.py
RuleID: "Amazon.EKS.AnonymousAPIAccess"
DisplayName: "EKS Anonymous API Access Detected"
Enabled: true
LogTypes:
- Amazon.EKS.Audit
Severity: Low
Reports:
MITRE ATT&CK:
- "TA0001:T1190" # Initial Access: Exploit Public-Facing Application
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://raesene.github.io/blog/2023/03/18/lets-talk-about-anonymous-access-to-Kubernetes/
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.
SummaryAttributes:
- user:username
- p_any_ip_addresses
- p_source_label
Tags:
- EKS
- Security Control
- API
- Initial Access:Exploit Public-Facing Application
Stages and Predicates
Fires on Amazon.EKS.Audit events when the condition below holds.
Condition
user.usernameissystem:anonymous
This rule also runs imperative logic the parser cannot express as a filter. The conditions above are the structured part it could extract.
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
user.username | eq |
| field:"user.username" kind:eq value:"system:anonymous" |
Output fields
Fields the rule emits when it matches, drawn from the rule's alert_context.
| Field |
|---|
requestURI |
Response 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.
Worked example
A sample event from the rule's unit tests that triggers a match.Sample Test Event
{
"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"
}