Kubernetes Suspicious Probing And Subsequent Escalation Activity
Query
let Lookback = 1d;
let ProbeBin = 30m;
let FollowUp = 1h;
let Audit = CloudAuditEvents
| where Timestamp > ago(Lookback)
| where DataSource =~ "Kubernetes Audit"
| extend User = tostring(RawEventData.user.username),
Verb = tolower(tostring(RawEventData.verb)),
Resource = tolower(tostring(RawEventData.objectRef.resource)),
SubResource = tolower(tostring(RawEventData.objectRef.subresource)),
Namespace = tostring(RawEventData.objectRef.namespace),
Code = toint(RawEventData.responseStatus.code),
SourceIp = tostring(RawEventData.sourceIPs[0])
| extend Action = strcat(Verb, " ", Resource, iff(isnotempty(SubResource), strcat("/", SubResource), ""))
| where not(User startswith "system:") or User startswith "system:serviceaccount:"
| where not(User startswith "system:serviceaccount:kube-system:");
let Probing = Audit
| extend IsSelfReview = Resource in ("selfsubjectrulesreviews", "selfsubjectaccessreviews")
| where IsSelfReview or Code == 403
| summarize SelfReviews = countif(IsSelfReview),
Forbidden = countif(Code == 403),
DeniedActions = make_set_if(Action, Code == 403, 50),
ProbeStart = min(Timestamp), ProbeEnd = max(Timestamp)
by User, AzureResourceId, SourceIp, bin(Timestamp, ProbeBin)
| where (SelfReviews > 0 and Forbidden > 0) or array_length(DeniedActions) >= 5;
let Escalation = Audit
| where Code between (200 .. 299)
| extend ImpersonatedUser = tostring(RawEventData.impersonatedUser.username)
| where (Resource == "secrets" and Verb in ("get", "list", "watch"))
or (Resource == "pods" and SubResource in ("exec", "attach"))
or (Resource == "pods" and Verb == "create" and isempty(SubResource))
or (Resource in ("rolebindings", "clusterrolebindings", "roles", "clusterroles") and Verb in ("create", "update", "patch"))
or (Resource == "serviceaccounts" and SubResource == "token")
or (Resource == "nodes" and SubResource == "proxy")
or isnotempty(ImpersonatedUser)
| project EscAt = Timestamp, User, AzureResourceId, Action, Namespace, ImpersonatedUser;
Probing
| join kind=inner Escalation on User, AzureResourceId
| where EscAt between (ProbeStart .. (ProbeEnd + FollowUp))
| summarize FirstProbe = min(ProbeStart), FirstEscalation = min(EscAt),
SelfReviews = max(SelfReviews), Forbidden = max(Forbidden),
DeniedActions = take_any(DeniedActions),
SuccessfulActions = make_set(Action, 30),
Namespaces = make_set(Namespace, 20),
ImpersonatedUsers = make_set_if(ImpersonatedUser, isnotempty(ImpersonatedUser))
by User, AzureResourceId, SourceIpAbout this query
Kubernetes Suspicious Probing and Subsequent Escalation Activity
Query Information
MITRE ATT&CK Technique(s)
| Technique ID | Title | Link |
|---|---|---|
| T1613 | Container and Resource Discovery | https://attack.mitre.org/techniques/T1613 |
| T1078 | Valid Accounts | https://attack.mitre.org/techniques/T1078 |
Description
This rule detects a multi-stage attack pattern in Kubernetes environments where an entity first performs suspicious probing activities (e.g., numerous self-subject rules/access reviews or repeated 403 Forbidden errors) followed by privileged or sensitive API actions within a short timeframe. The logic correlates reconnaissance attempts against the API server with subsequent successful escalation-related operations such as accessing secrets, pod execution, or role/clusterrole modifications.
Author <Optional>
- Name: Benjamin Zulliger
- Github: https://github.com/benscha/KQLAdvancedHunting
- LinkedIn: https://www.linkedin.com/in/benjamin-zulliger/
Defender XDR
Explanation
This query is designed to detect suspicious activity in Kubernetes environments that may indicate a multi-stage attack. Here's a simplified breakdown of what the query does:
-
Timeframe and Data Source: It looks at Kubernetes audit logs from the past day (
Lookback = 1d). -
Probing Activity:
- It identifies suspicious probing activities by checking for:
- Self-subject rules or access reviews.
- Repeated 403 Forbidden errors.
- It groups these activities into 30-minute intervals (
ProbeBin = 30m). - It flags users who have both self-reviews and forbidden actions or have a significant number of denied actions.
- It identifies suspicious probing activities by checking for:
-
Escalation Activity:
- It looks for successful actions (HTTP status codes 200-299) that indicate privilege escalation, such as:
- Accessing secrets.
- Executing or attaching to pods.
- Creating or modifying roles and cluster roles.
- Impersonating other users.
- These actions are considered within an hour (
FollowUp = 1h) after the probing activity.
- It looks for successful actions (HTTP status codes 200-299) that indicate privilege escalation, such as:
-
Correlation:
- It correlates the probing activities with subsequent escalation activities by matching the user and resource ID.
- It checks if the escalation happened within the timeframe of the probing activity plus the follow-up period.
-
Summary:
- The query summarizes the findings by user, resource ID, and source IP.
- It provides details such as the first probe and escalation times, counts of self-reviews and forbidden actions, denied and successful actions, namespaces involved, and any impersonated users.
Overall, this query helps identify potential security threats by detecting patterns of reconnaissance followed by privilege escalation in Kubernetes environments.