Query Details

Kubernetes Suspicious Service Account Creation And Token Minting

Query

let Lookback = 1d;
let ChainWindow = 1h;
let AllowedAutomation = dynamic(["system:serviceaccount:argocd:argocd-application-controller"]);
let Audit = CloudAuditEvents
| where Timestamp > ago(Lookback)
| where DataSource =~ "Kubernetes Audit"
| extend Verb = tolower(tostring(RawEventData.verb)),
         Resource = tolower(tostring(RawEventData.objectRef.resource)),
         SubResource = tolower(tostring(RawEventData.objectRef.subresource)),
         Namespace = tostring(RawEventData.objectRef.namespace),
         ObjName = tostring(RawEventData.objectRef.name),
         Actor = tostring(RawEventData.user.username),
         SourceIp = tostring(RawEventData.sourceIPs[0]),
         Code = toint(RawEventData.responseStatus.code),
         Req = RawEventData.requestObject
| where Verb == "create" and Code between (200 .. 299)
| where Actor !in (AllowedAutomation) and not(Actor startswith "system:node:");
let SACreated = Audit
| where Resource == "serviceaccounts" and isempty(SubResource)
| project SACreatedAt = Timestamp, AzureResourceId, Actor, SourceIp, Namespace,
          SAName = coalesce(ObjName, tostring(Req.metadata.name));
let Bindings = Audit
| where Resource in ("rolebindings", "clusterrolebindings")
| mv-expand Subject = Req.subjects
| where tostring(Subject.kind) == "ServiceAccount"
| project BindAt = Timestamp, AzureResourceId, Actor,
          Namespace = coalesce(tostring(Subject.namespace), Namespace),
          SAName = tostring(Subject.name),
          BindingKind = Resource, RoleRef = tostring(Req.roleRef.name);
let TokenMint = union
    (Audit
     | where Resource == "serviceaccounts" and SubResource == "token"
     | project MintAt = Timestamp, AzureResourceId, Actor, Namespace, SAName = ObjName,
               MintType = "TokenRequest", ExpirationSec = tolong(Req.spec.expirationSeconds)),
    (Audit
     | where Resource == "secrets" and tostring(Req.type) == "kubernetes.io/service-account-token"
     | project MintAt = Timestamp, AzureResourceId, Actor, Namespace,
               SAName = tostring(Req.metadata.annotations["kubernetes.io/service-account.name"]),
               MintType = "LegacySecretToken", ExpirationSec = long(null));
SACreated
| join kind=inner Bindings on AzureResourceId, Actor, Namespace, SAName
| where BindAt between (SACreatedAt .. (SACreatedAt + ChainWindow))
| join kind=inner TokenMint on AzureResourceId, Actor, Namespace, SAName
| where MintAt between (SACreatedAt .. (SACreatedAt + ChainWindow))
| extend Severity = case(RoleRef in ("cluster-admin", "admin", "edit") or BindingKind == "clusterrolebindings", "High",
                         MintType == "LegacySecretToken" or ExpirationSec > 86400, "High",
                         "Medium")
| project SACreatedAt, BindAt, MintAt, Actor, SourceIp, AzureResourceId, Namespace, SAName,
          BindingKind, RoleRef, MintType, ExpirationSec, Severity

About this query

Kubernetes Suspicious Service Account Creation and Token Minting

Query Information

MITRE ATT&CK Technique(s)

Technique IDTitleLink
T1136.001Local Accounthttps://attack.mitre.org/techniques/T1136/001
T1528Steal Application Access Tokenhttps://attack.mitre.org/techniques/T1528
T1098.003Additional Cloud Roleshttps://attack.mitre.org/techniques/T1098/003

Description

This rule detects a sequence of suspicious Kubernetes activities involving the creation of a new Service Account, followed by the attachment of high-privilege RoleBindings (admin, edit, or cluster-admin) to that account, and finally the requesting of an authentication token for the newly created account. This pattern is indicative of a privilege escalation attempt where an adversary attempts to create a persistent, highly-privileged identity within the cluster.

Author <Optional>

Defender XDR

Explanation

This query is designed to detect potentially malicious activities in a Kubernetes environment. Specifically, it looks for a sequence of actions that could indicate an attempt to escalate privileges within the cluster. Here's a simplified breakdown of what the query does:

  1. Timeframe and Exclusions:

    • It examines Kubernetes audit logs from the past day (Lookback = 1d).
    • It excludes certain automated actions from trusted service accounts (AllowedAutomation).
  2. Audit Log Filtering:

    • It filters the logs to focus on "create" actions that were successful (HTTP status codes 200-299) and not performed by system nodes or allowed automation.
  3. Service Account Creation:

    • It identifies when a new service account is created.
  4. Role Binding:

    • It checks if the newly created service account is granted high-privilege roles (like admin or cluster-admin) through role bindings.
  5. Token Minting:

    • It looks for requests to mint authentication tokens for the service account, which could be used to access the cluster with elevated privileges.
  6. Correlation and Severity:

    • It correlates these events (service account creation, role binding, and token minting) if they occur within an hour of each other (ChainWindow = 1h).
    • It assigns a severity level based on the type of role binding and token minting, flagging high-risk activities.
  7. Output:

    • The query outputs details of these suspicious activities, including timestamps, actor information, source IP, and severity level.

Overall, this query helps security teams identify and respond to potential privilege escalation attempts in Kubernetes by monitoring for suspicious service account activities.