Kubernetes DaemonSet Created


Description

This detection monitors for creation of DaemonSets in Kubernetes clusters. DaemonSets ensure that a copy of a pod runs on all (or selected) nodes in the cluster. Attackers may abuse DaemonSets to deploy malicious containers across all nodes for cluster-wide persistence, credential harvesting, cryptomining, or lateral movement. This detection works across AWS EKS, Azure AKS, and GCP GKE clusters.

Query · python

from panther_kubernetes_helpers import (
    is_failed_request,
    is_system_namespace,
    is_system_principal,
    k8s_alert_context,
)


def rule(event):
    verb = event.udm("verb")
    resource = event.udm("resource")
    response_status = event.udm("responseStatus")
    namespace = event.udm("namespace")
    username = event.udm("username")

    # Check for DaemonSet create operation
    if verb == "create" and resource == "daemonsets":
        # Only alert on successful operations
        if is_failed_request(response_status):
            return False

        # Exclude system controllers creating DaemonSets in system namespaces
        if is_system_namespace(namespace) and is_system_principal(username):
            return False

        return True

    return False


def title(event):
    username = event.udm("username") or "<UNKNOWN_USER>"
    namespace = event.udm("namespace") or "<UNKNOWN_NAMESPACE>"
    daemonset_name = event.udm("name") or "<UNKNOWN>"

    return f"[{username}] created DaemonSet [{namespace}/{daemonset_name}]"


def dedup(event):
    username = event.udm("username") or "<UNKNOWN_USER>"
    namespace = event.udm("namespace") or "<UNKNOWN_NAMESPACE>"
    return f"k8s_daemonset_{username}_{namespace}"


def alert_context(event):
    return k8s_alert_context(
        event,
        extra_fields={
            "daemonset_name": event.udm("name"),
            "requestObject": event.udm("requestObject"),
        },
    )

Analyst notes

  1. Review all DaemonSet and Deployment creation events by username in the 24 hours before the alert to establish if this is routine activity
  2. Analyze the container image, hostPath volumes, and privileged security context from the requestObject specification to identify risk factors
  3. Search for similar DaemonSet deployments by this user in the past 90 days and compare images, namespaces, and security settings to identify anomalies
Raw source Kubernetes DaemonSet Created · Panther Python
Esc
Published by panther-labs/panther-analysis ↗, licensed under Apache 2.0 ↗. Reproduced here unmodified.
AnalysisType: rule
RuleID: "Kubernetes.DaemonSet.Created"
DisplayName: "Kubernetes DaemonSet Created"
Enabled: true
Filename: k8s_daemonset_created.py
LogTypes:
  - Amazon.EKS.Audit
  - Azure.MonitorActivity
  - GCP.AuditLog
Tags:
  - Kubernetes
  - Security Control
  - Persistence
  - Deploy Container
  - Unified Detection
Severity: Info
Description: >
  This detection monitors for creation of DaemonSets in Kubernetes clusters.
  DaemonSets ensure that a copy of a pod runs on all (or selected) nodes in the cluster.
  Attackers may abuse DaemonSets to deploy malicious containers across all nodes for
  cluster-wide persistence, credential harvesting, cryptomining, or lateral movement.
  This detection works across AWS EKS, Azure AKS, and GCP GKE clusters.
Runbook: |
  1. Review all DaemonSet and Deployment creation events by username in the 24 hours before the alert to establish if this is routine activity
  2. Analyze the container image, hostPath volumes, and privileged security context from the requestObject specification to identify risk factors
  3. Search for similar DaemonSet deployments by this user in the past 90 days and compare images, namespaces, and security settings to identify anomalies
Reference: https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/
Reports:
  MITRE ATT&CK:
    - TA0002:T1610 # Execution: Deploy Container
    - TA0003:T1543 # Persistence: Create or Modify System Process
DedupPeriodMinutes: 60
SummaryAttributes:
  - username
  - namespace
  - p_source_label
Tests:
  - Name: EKS DaemonSet Created
    ExpectedResult: true
    Log:
      {
        "kind": "Event",
        "apiVersion": "audit.k8s.io/v1",
        "auditID": "abc-123",
        "verb": "create",
        "user": {"username": "admin@example.com"},
        "sourceIPs": ["1.2.3.4"],
        "userAgent": "kubectl/v1.28.0",
        "objectRef": {
          "resource": "daemonsets",
          "namespace": "kube-system",
          "name": "monitoring-agent",
          "apiVersion": "apps/v1"
        },
        "responseStatus": {"code": 201},
        "requestURI": "/apis/apps/v1/namespaces/kube-system/daemonsets",
        "requestObject": {
          "kind": "DaemonSet",
          "metadata": {"name": "monitoring-agent", "namespace": "kube-system"},
          "spec": {
            "selector": {"matchLabels": {"app": "monitoring"}},
            "template": {
              "metadata": {"labels": {"app": "monitoring"}},
              "spec": {
                "containers": [{
                  "name": "agent",
                  "image": "monitoring-agent:latest",
                  "volumeMounts": [{
                    "name": "docker-sock",
                    "mountPath": "/var/run/docker.sock"
                  }]
                }],
                "volumes": [{
                  "name": "docker-sock",
                  "hostPath": {"path": "/var/run/docker.sock"}
                }]
              }
            }
          }
        },
        "p_log_type": "Amazon.EKS.Audit",
        "p_source_label": "eks-cluster"
      }
  - Name: AKS DaemonSet Created
    ExpectedResult: true
    Log:
      {
        "p_log_type": "Azure.MonitorActivity",
        "category": "kube-audit",
        "operationName": "Microsoft.ContainerService/managedClusters/diagnosticLogs/Read",
        "properties": {
          "log": "{\"kind\":\"Event\",\"apiVersion\":\"audit.k8s.io/v1\",\"verb\":\"create\",\"user\":{\"username\":\"admin@example.com\"},\"sourceIPs\":[\"10.0.0.1\"],\"objectRef\":{\"resource\":\"daemonsets\",\"namespace\":\"default\",\"name\":\"log-collector\"},\"responseStatus\":{\"code\":201},\"requestURI\":\"/apis/apps/v1/namespaces/default/daemonsets\"}"
        },
        "p_source_label": "aks-cluster"
      }
  - Name: GCP GKE DaemonSet Created
    ExpectedResult: true
    Log:
      {
        "protoPayload": {
          "authenticationInfo": {"principalEmail": "user@company.com"},
          "authorizationInfo": [{
            "granted": true,
            "permission": "io.k8s.apps.v1.daemonsets.create",
            "resource": "apps/v1/namespaces/kube-system/daemonsets/node-exporter"
          }],
          "methodName": "io.k8s.apps.v1.daemonsets.create",
          "requestMetadata": {
            "callerIP": "1.2.3.4",
            "callerSuppliedUserAgent": "kubectl/v1.27.0"
          },
          "resourceName": "apps/v1/namespaces/kube-system/daemonsets/node-exporter",
          "serviceName": "k8s.io",
          "request": {
            "kind": "DaemonSet",
            "metadata": {"name": "node-exporter", "namespace": "kube-system"}
          }
        },
        "resource": {
          "type": "k8s_cluster",
          "labels": {"project_id": "test-project"}
        },
        "p_log_type": "GCP.AuditLog",
        "p_source_label": "gke-cluster"
      }
  - Name: DaemonSet Creation Failed
    ExpectedResult: false
    Log:
      {
        "kind": "Event",
        "verb": "create",
        "objectRef": {
          "resource": "daemonsets",
          "namespace": "default",
          "name": "test-ds"
        },
        "responseStatus": {"code": 403, "status": "Failure"},
        "p_log_type": "Amazon.EKS.Audit"
      }
  - Name: Deployment Creation (Not DaemonSet)
    ExpectedResult: false
    Log:
      {
        "kind": "Event",
        "verb": "create",
        "objectRef": {
          "resource": "deployments",
          "namespace": "default",
          "name": "web-app"
        },
        "responseStatus": {"code": 201},
        "p_log_type": "Amazon.EKS.Audit"
      }
  - Name: DaemonSet Update (Not Create)
    ExpectedResult: false
    Log:
      {
        "kind": "Event",
        "verb": "update",
        "objectRef": {
          "resource": "daemonsets",
          "namespace": "kube-system",
          "name": "existing-ds"
        },
        "responseStatus": {"code": 200},
        "p_log_type": "Amazon.EKS.Audit"
      }
  - Name: System controller creating DaemonSet in kube-system (excluded)
    ExpectedResult: false
    Log:
      {
        "kind": "Event",
        "apiVersion": "audit.k8s.io/v1",
        "verb": "create",
        "user": {"username": "system:serviceaccount:kube-system:daemon-set-controller"},
        "sourceIPs": ["10.0.0.1"],
        "objectRef": {
          "resource": "daemonsets",
          "namespace": "kube-system",
          "name": "kube-proxy",
          "apiVersion": "apps/v1"
        },
        "responseStatus": {"code": 201},
        "p_log_type": "Amazon.EKS.Audit",
        "p_source_label": "eks-cluster"
      }


# ------ paired body: k8s_daemonset_created.py ------

from panther_kubernetes_helpers import (
    is_failed_request,
    is_system_namespace,
    is_system_principal,
    k8s_alert_context,
)


def rule(event):
    verb = event.udm("verb")
    resource = event.udm("resource")
    response_status = event.udm("responseStatus")
    namespace = event.udm("namespace")
    username = event.udm("username")

    # Check for DaemonSet create operation
    if verb == "create" and resource == "daemonsets":
        # Only alert on successful operations
        if is_failed_request(response_status):
            return False

        # Exclude system controllers creating DaemonSets in system namespaces
        if is_system_namespace(namespace) and is_system_principal(username):
            return False

        return True

    return False


def title(event):
    username = event.udm("username") or "<UNKNOWN_USER>"
    namespace = event.udm("namespace") or "<UNKNOWN_NAMESPACE>"
    daemonset_name = event.udm("name") or "<UNKNOWN>"

    return f"[{username}] created DaemonSet [{namespace}/{daemonset_name}]"


def dedup(event):
    username = event.udm("username") or "<UNKNOWN_USER>"
    namespace = event.udm("namespace") or "<UNKNOWN_NAMESPACE>"
    return f"k8s_daemonset_{username}_{namespace}"


def alert_context(event):
    return k8s_alert_context(
        event,
        extra_fields={
            "daemonset_name": event.udm("name"),
            "requestObject": event.udm("requestObject"),
        },
    )

Detection rules belong to the projects that publish them and remain under their own licenses. This site indexes and links to them; it claims no rights in them.