Kubernetes Pod Attached To Host Network


Description

This detection monitors for the creation of pods which are attached to the host's network. This allows a pod to listen to all network traffic for all deployed compute on that particular node and communicate with other compute on the network namespace. Attackers can use this to capture secrets passed in arguments or connections.

Query · python

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


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

    # Only check pod creation events
    if verb != "create" or resource != "pods":
        return False

    # Skip failed requests
    if is_failed_request(response_status):
        return False

    # Exclude system principals creating pods in system namespaces (legitimate)
    # but alert on system principals in user namespaces (malicious Deployments)
    # and alert on user-created pods in system namespaces (suspicious)
    if is_system_principal(username) and is_system_namespace(namespace):
        return False

    # Check if hostNetwork is set to true in the request
    host_network = event.udm("hostNetwork")
    if host_network is True:
        return True

    return False


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

    return f"[{username}] created pod [{namespace}/{name}] with host network access "


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


def alert_context(event):
    return k8s_alert_context(event, extra_fields=get_pod_context_fields(event))

Analyst notes

  1. Find all pod creation events by the username in the 24 hours before the alert to establish normal deployment behavior
  2. Check if the pod namespace indicates system infrastructure purpose (kube-system, kube-public) which may be legitimate
  3. Review all pods with hostNetwork by this user in the past 30 days to identify if this is an established pattern or anomalous activity
Raw source Kubernetes Pod Attached To Host Network · Panther Python
Esc
Published by panther-labs/panther-analysis ↗, licensed under Apache 2.0 ↗. Reproduced here unmodified.
AnalysisType: rule
RuleID: "Kubernetes.Pod.Host.Network"
DisplayName: "Kubernetes Pod Attached To Host Network"
Enabled: true
Filename: k8s_pod_host_network.py
LogTypes:
  - Amazon.EKS.Audit
  - Azure.MonitorActivity
  - GCP.AuditLog
Tags:
  - Kubernetes
  - Security Control
  - Escape to Host
  - Unified Detection
Severity: Medium
Description:
  This detection monitors for the creation of pods which are attached to the host's network.
  This allows a pod to listen to all network traffic for all deployed compute on that particular
  node and communicate with other compute on the network namespace. Attackers can use this to
  capture secrets passed in arguments or connections.
Reports:
  MITRE ATT&CK:
    - TA0004:T1611 # Escape to Host
Runbook: |
  1. Find all pod creation events by the username in the 24 hours before the alert to establish normal deployment behavior
  2. Check if the pod namespace indicates system infrastructure purpose (kube-system, kube-public) which may be legitimate
  3. Review all pods with hostNetwork by this user in the past 30 days to identify if this is an established pattern or anomalous activity
Reference: >
  - https://kubernetes.io/docs/concepts/security/pod-security-standards/#host-namespaces
  - https://securitylabs.datadoghq.com/articles/kubernetes-security-fundamentals-part-6/
Tests:
  - Name: EKS Pod With Host Network
    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": "pods",
          "namespace": "default",
          "name": "nginx-test",
          "apiVersion": "v1"
        },
        "responseStatus": {"code": 201},
        "requestObject": {
          "kind": "Pod",
          "apiVersion": "v1",
          "metadata": {"name": "nginx-test", "namespace": "default"},
          "spec": {
            "hostNetwork": true,
            "containers": [{"name": "nginx", "image": "nginx"}]
          }
        },
        "p_log_type": "Amazon.EKS.Audit",
        "p_source_label": "eks-cluster"
      }
  - Name: AKS Pod With Host Network
    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\",\"auditID\":\"abc-123\",\"verb\":\"create\",\"user\":{\"username\":\"admin@example.com\"},\"sourceIPs\":[\"10.0.0.1\"],\"objectRef\":{\"resource\":\"pods\",\"namespace\":\"default\",\"name\":\"nginx-test\"},\"responseStatus\":{\"code\":201},\"requestObject\":{\"kind\":\"Pod\",\"spec\":{\"hostNetwork\":true,\"containers\":[{\"name\":\"nginx\",\"image\":\"nginx\"}]}}}"
        },
        "p_source_label": "aks-cluster"
      }
  - Name: GCP GKE Pod With Host Network
    ExpectedResult: true
    Log:
      {
        "protoPayload": {
          "authenticationInfo": {"principalEmail": "user@example.com"},
          "authorizationInfo": [{
            "granted": true,
            "permission": "io.k8s.core.v1.pods.create",
            "resource": "core/v1/namespaces/default/pods/nginx-test"
          }],
          "methodName": "io.k8s.core.v1.pods.create",
          "request": {
            "@type": "core.k8s.io/v1.Pod",
            "spec": {
              "hostNetwork": true,
              "containers": [{"name": "nginx", "image": "nginx"}]
            }
          },
          "requestMetadata": {"callerIP": "1.2.3.4"},
          "resourceName": "core/v1/namespaces/default/pods/nginx-test",
          "serviceName": "k8s.io"
        },
        "resource": {
          "type": "k8s_cluster",
          "labels": {"project_id": "test-project"}
        },
        "p_log_type": "GCP.AuditLog",
        "p_source_label": "gke-cluster"
      }
  - Name: Pod Without Host Network
    ExpectedResult: false
    Log:
      {
        "kind": "Event",
        "verb": "create",
        "objectRef": {"resource": "pods", "namespace": "default"},
        "responseStatus": {"code": 201},
        "requestObject": {
          "kind": "Pod",
          "spec": {
            "hostNetwork": false,
            "containers": [{"name": "nginx", "image": "nginx"}]
          }
        },
        "p_log_type": "Amazon.EKS.Audit"
      }
  - Name: Pod Creation Failed
    ExpectedResult: false
    Log:
      {
        "kind": "Event",
        "verb": "create",
        "objectRef": {"resource": "pods", "namespace": "default"},
        "responseStatus": {"code": 403, "status": "Failure"},
        "requestObject": {
          "kind": "Pod",
          "spec": {
            "hostNetwork": true,
            "containers": [{"name": "nginx"}]
          }
        },
        "p_log_type": "Amazon.EKS.Audit"
      }
  - Name: Not a Pod Creation
    ExpectedResult: false
    Log:
      {
        "kind": "Event",
        "verb": "get",
        "objectRef": {"resource": "pods", "namespace": "default"},
        "p_log_type": "Amazon.EKS.Audit"
      }


# ------ paired body: k8s_pod_host_network.py ------

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


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

    # Only check pod creation events
    if verb != "create" or resource != "pods":
        return False

    # Skip failed requests
    if is_failed_request(response_status):
        return False

    # Exclude system principals creating pods in system namespaces (legitimate)
    # but alert on system principals in user namespaces (malicious Deployments)
    # and alert on user-created pods in system namespaces (suspicious)
    if is_system_principal(username) and is_system_namespace(namespace):
        return False

    # Check if hostNetwork is set to true in the request
    host_network = event.udm("hostNetwork")
    if host_network is True:
        return True

    return False


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

    return f"[{username}] created pod [{namespace}/{name}] with host network access "


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


def alert_context(event):
    return k8s_alert_context(event, extra_fields=get_pod_context_fields(event))

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.