Install this skill
npx skills add mukul975/Anthropic-Cybersecurity-SkillsFramework mappings
MITRE ATT&CK
T1068 on the official MITRE ATT&CK siteT1078 on the official MITRE ATT&CK siteT1136 on the official MITRE ATT&CK siteT1525 on the official MITRE ATT&CK siteT1548 on the official MITRE ATT&CK siteT1609 on the official MITRE ATT&CK siteT1610 on the official MITRE ATT&CK siteT1611 on the official MITRE ATT&CK site
NIST CSF 2.0
Overview
Privilege escalation in Kubernetes occurs when a pod or container gains elevated permissions beyond its intended scope. This includes running as root, using privileged mode, mounting host filesystems, enabling dangerous Linux capabilities, or exploiting kernel vulnerabilities. Detection combines admission control (prevention), runtime monitoring (detection), and audit logging (investigation).
When to Use
- When investigating security incidents that require detecting privilege escalation in kubernetes pods
- When building detection rules or threat hunting queries for this domain
- When SOC analysts need structured procedures for this analysis type
- When validating security monitoring coverage for related attack techniques
Prerequisites
- Kubernetes cluster v1.25+ (Pod Security Admission support)
- kubectl with cluster-admin access
- Falco or similar runtime security tool
- OPA Gatekeeper or Kyverno for admission policies
Privilege Escalation Vectors in Kubernetes
| Vector | Risk | Detection Method |
|---|---|---|
| privileged: true | Full host access | Admission control + audit |
| hostPID: true | Access host processes | Admission control |
| hostNetwork: true | Access host network stack | Admission control |
| hostPath volumes | Read/write host filesystem | Admission control |
| SYS_ADMIN capability | Near-privileged access | Admission + runtime |
| allowPrivilegeEscalation: true | setuid/setgid exploitation | Admission control |
| runAsUser: 0 | Container root | Admission control |
| automountServiceAccountToken | Token theft for API access | Admission control |
| Writable /proc or /sys | Kernel parameter manipulation | Runtime monitoring |
Detection with Admission Control
Pod Security Admission (Built-in)
# Enforce restricted policy on namespace
apiVersion: v1
kind: Namespace
metadata:
name: production
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/enforce-version: latest
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/warn: restrictedOPA Gatekeeper Policies
# Block dangerous capabilities
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
name: k8sdangerouspriv
spec:
crd:
spec:
names:
kind: K8sDangerousPriv
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8sdangerouspriv
dangerous_caps := {"SYS_ADMIN", "SYS_PTRACE", "SYS_MODULE", "DAC_OVERRIDE", "NET_ADMIN", "NET_RAW"}
violation[{"msg": msg}] {
container := input.review.object.spec.containers[_]
cap := container.securityContext.capabilities.add[_]
dangerous_caps[cap]
msg := sprintf("Container %v adds dangerous capability: %v", [container.name, cap])
}
violation[{"msg": msg}] {
container := input.review.object.spec.containers[_]
container.securityContext.privileged == true
msg := sprintf("Container %v runs in privileged mode", [container.name])
}
violation[{"msg": msg}] {
container := input.review.object.spec.containers[_]
container.securityContext.allowPrivilegeEscalation == true
msg := sprintf("Container %v allows privilege escalation", [container.name])
}
violation[{"msg": msg}] {
input.review.object.spec.hostPID == true
msg := "Pod uses host PID namespace"
}
violation[{"msg": msg}] {
input.review.object.spec.hostNetwork == true
msg := "Pod uses host network"
}Runtime Detection with Falco
# /etc/falco/rules.d/privesc-detection.yaml
- rule: Setuid Binary Execution in Container
desc: Detect execution of setuid/setgid binaries in a container
condition: >
spawned_process and container and
(proc.name in (su, sudo, newgrp, chsh, passwd) or
proc.is_exe_upper_layer=true)
output: >
Setuid/setgid binary executed in container
(user=%user.name container=%container.name image=%container.image.repository
command=%proc.cmdline parent=%proc.pname)
priority: WARNING
tags: [container, privilege-escalation, T1548]
- rule: Capability Gained in Container
desc: Detect when a process gains elevated capabilities
condition: >
evt.type = capset and container and
evt.arg.cap != ""
output: >
Process gained capabilities in container
(container=%container.name image=%container.image.repository
capabilities=%evt.arg.cap command=%proc.cmdline)
priority: WARNING
tags: [container, privilege-escalation, T1548.001]
- rule: Container with Dangerous Capabilities Started
desc: Detect container launched with dangerous capabilities
condition: >
container_started and container and
(container.image.repository != "registry.k8s.io/pause") and
(container.cap_effective contains SYS_ADMIN or
container.cap_effective contains SYS_PTRACE or
container.cap_effective contains SYS_MODULE)
output: >
Container with dangerous capabilities
(container=%container.name image=%container.image.repository
caps=%container.cap_effective)
priority: CRITICAL
tags: [container, privilege-escalation, T1068]
- rule: Write to /etc/passwd in Container
desc: Detect writes to /etc/passwd inside container
condition: >
open_write and container and fd.name = /etc/passwd
output: >
Write to /etc/passwd in container
(container=%container.name image=%container.image.repository
command=%proc.cmdline user=%user.name)
priority: CRITICAL
tags: [container, privilege-escalation, T1136]Kubernetes Audit Log Detection
# audit-policy.yaml - Capture privilege escalation events
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
# Log pod creation with security context details
- level: RequestResponse
resources:
- group: ""
resources: ["pods"]
verbs: ["create", "update", "patch"]
# Log privilege escalation attempts
- level: RequestResponse
resources:
- group: "rbac.authorization.k8s.io"
resources: ["clusterroles", "clusterrolebindings", "roles", "rolebindings"]
verbs: ["create", "update", "patch", "bind", "escalate"]
# Log service account token requests
- level: Metadata
resources:
- group: ""
resources: ["serviceaccounts/token"]
verbs: ["create"]Query Audit Logs for Privilege Escalation
# Find pods created with privileged security context
kubectl logs -n kube-system kube-apiserver-* | \
jq 'select(.verb == "create" and .objectRef.resource == "pods") |
select(.requestObject.spec.containers[].securityContext.privileged == true)'
# Find RBAC escalation attempts
kubectl logs -n kube-system kube-apiserver-* | \
jq 'select(.objectRef.resource == "clusterrolebindings" and .verb == "create")'Investigation Playbook
# Check pod security context
kubectl get pod <pod-name> -n <ns> -o jsonpath='{.spec.containers[*].securityContext}'
# Check effective capabilities
kubectl exec <pod-name> -n <ns> -- cat /proc/1/status | grep -i cap
# List pods running as root
kubectl get pods --all-namespaces -o json | \
jq '.items[] | select(.spec.containers[].securityContext.runAsUser == 0 or .spec.containers[].securityContext.privileged == true) | {name: .metadata.name, ns: .metadata.namespace}'
# Check for hostPath volumes
kubectl get pods --all-namespaces -o json | \
jq '.items[] | select(.spec.volumes[]?.hostPath != null) | {name: .metadata.name, ns: .metadata.namespace, paths: [.spec.volumes[].hostPath.path]}'Best Practices
- Enable Pod Security Admission at
restrictedlevel for production namespaces - Drop ALL capabilities and add back only what is needed
- Set allowPrivilegeEscalation: false on all containers
- Run as non-root (runAsNonRoot: true, runAsUser > 0)
- Disable automountServiceAccountToken unless API access is needed
- Monitor with Falco for runtime privilege escalation attempts
- Audit RBAC changes with Kubernetes audit logging
- Use seccomp profiles to restrict syscalls
Source materials
References and resources
Everything below is rendered for inspection. Script files are read-only and never run.
References 3
api-reference.md1.2 KB
API Reference: Detecting Privilege Escalation in Kubernetes Pods
Security Context Checks
| Check | Risk | Description |
|---|---|---|
| privileged: true | CRITICAL | Full host access |
| allowPrivilegeEscalation | HIGH | setuid escalation |
| runAsUser: 0 | HIGH | Running as root |
| hostPID: true | CRITICAL | Host PID namespace |
| hostNetwork: true | HIGH | Host network access |
Dangerous Capabilities
| Capability | Risk |
|---|---|
| SYS_ADMIN | Container escape |
| SYS_PTRACE | Process debugging |
| SYS_MODULE | Kernel module loading |
| NET_ADMIN | Network manipulation |
kubectl Audit Commands
kubectl get pods -A -o json | jq '.items[] | select(.spec.containers[].securityContext.privileged==true)'
kubectl auth can-i --list --as=system:serviceaccount:ns:saPod Security Standards
apiVersion: v1
kind: Namespace
metadata:
labels:
pod-security.kubernetes.io/enforce: restrictedFalco Rules
- rule: Pod with Privileged Container
condition: kevt and kcreate and container.privileged=true
priority: CRITICALCLI Usage
python agent.py --namespace default
python agent.py --json-file pods.jsonstandards.md1.0 KB
Standards - Detecting Privilege Escalation in Kubernetes Pods
MITRE ATT&CK for Containers
| Technique | ID | Description |
|---|---|---|
| Escape to Host | T1611 | Container breakout via privilege escalation |
| Exploitation for Privilege Escalation | T1068 | Kernel exploit from container |
| Abuse Elevation Control | T1548 | Setuid/setgid binary exploitation |
| Valid Accounts | T1078 | Service account token theft |
| Create Account | T1136 | Modify /etc/passwd in container |
CIS Kubernetes Benchmark v1.8
- 5.2.1-5.2.9: Pod Security Standards
- 5.7.3: Apply security context to pods
NIST SP 800-190
- Section 4.3: Container runtime vulnerabilities
- Section 5.4: Runtime monitoring for privilege escalation
Pod Security Standards
| Profile | Level | Key Restrictions |
|---|---|---|
| Privileged | Unrestricted | No restrictions |
| Baseline | Minimally restrictive | No privileged, no hostPID/hostNetwork |
| Restricted | Heavily restricted | Non-root, drop all caps, no privilege escalation |
workflows.md1.2 KB
Workflow - Detecting Privilege Escalation in Kubernetes Pods
Phase 1: Assess Current State
# Find privileged pods
kubectl get pods -A -o json | jq '[.items[] | select(.spec.containers[].securityContext.privileged==true) | {name:.metadata.name, ns:.metadata.namespace}]'
# Find pods running as root
kubectl get pods -A -o json | jq '[.items[] | select(.spec.securityContext.runAsUser==0 or .spec.containers[].securityContext.runAsUser==0) | {name:.metadata.name, ns:.metadata.namespace}]'
# Find hostPath mounts
kubectl get pods -A -o json | jq '[.items[] | select(.spec.volumes[]?.hostPath!=null) | {name:.metadata.name, ns:.metadata.namespace}]'Phase 2: Deploy Prevention
- Apply Pod Security Admission labels to namespaces
- Deploy OPA Gatekeeper constraints
- Test with non-compliant pods (should be rejected)
Phase 3: Deploy Detection
- Install Falco with privilege escalation rules
- Enable Kubernetes audit logging
- Configure alerts to SIEM
Phase 4: Respond to Alerts
- Identify compromised pod
- Check container security context
- Review process list and capabilities
- Isolate with network policy
- Capture forensic data
- Delete compromised pod
Scripts 2
agent.py4.2 KB
Display-only source. This catalog never executes bundled scripts.
#!/usr/bin/env python3
"""Kubernetes pod privilege escalation detection agent.
Audits pod security contexts, capabilities, and service account permissions
to detect misconfigurations enabling container privilege escalation.
"""
import argparse
import json
import subprocess
from datetime import datetime
DANGEROUS_CAPABILITIES = {
"SYS_ADMIN", "SYS_PTRACE", "SYS_MODULE", "NET_ADMIN",
"NET_RAW", "DAC_READ_SEARCH", "SYS_RAWIO",
}
def get_pods(namespace="--all-namespaces"):
try:
cmd = ["kubectl", "get", "pods", "-o", "json"]
if namespace == "--all-namespaces":
cmd.append("--all-namespaces")
else:
cmd.extend(["-n", namespace])
result = subprocess.run(cmd, capture_output=True, text=True, timeout=30)
if result.returncode == 0:
return json.loads(result.stdout).get("items", [])
except (subprocess.TimeoutExpired, FileNotFoundError, json.JSONDecodeError):
pass
return []
def audit_pod(pod):
findings = []
pod_name = pod.get("metadata", {}).get("name", "")
namespace = pod.get("metadata", {}).get("namespace", "")
spec = pod.get("spec", {})
if spec.get("hostPID"):
findings.append({"check": "hostPID", "severity": "CRITICAL", "desc": "Host PID namespace"})
if spec.get("hostNetwork"):
findings.append({"check": "hostNetwork", "severity": "HIGH", "desc": "Host network"})
if spec.get("hostIPC"):
findings.append({"check": "hostIPC", "severity": "MEDIUM", "desc": "Host IPC"})
for container in spec.get("containers", []) + spec.get("initContainers", []):
ctx = container.get("securityContext", {})
c_name = container.get("name", "")
if ctx.get("privileged"):
findings.append({"container": c_name, "check": "privileged",
"severity": "CRITICAL", "desc": "Privileged container"})
if ctx.get("allowPrivilegeEscalation", True):
findings.append({"container": c_name, "check": "allowPrivilegeEscalation",
"severity": "HIGH", "desc": "Privilege escalation allowed"})
run_as = ctx.get("runAsUser")
if run_as == 0 or (run_as is None and not ctx.get("runAsNonRoot")):
findings.append({"container": c_name, "check": "runAsRoot",
"severity": "HIGH", "desc": "May run as root"})
if not ctx.get("readOnlyRootFilesystem"):
findings.append({"container": c_name, "check": "mutableFS",
"severity": "MEDIUM", "desc": "Writable root FS"})
caps = ctx.get("capabilities", {})
for cap in set(caps.get("add", [])) & DANGEROUS_CAPABILITIES:
findings.append({"container": c_name, "check": "dangerous_cap",
"capability": cap, "severity": "CRITICAL"})
for vm in container.get("volumeMounts", []):
if vm.get("mountPath") in ("/var/run/docker.sock", "/run/containerd/containerd.sock"):
findings.append({"container": c_name, "check": "runtime_socket",
"severity": "CRITICAL", "desc": f"Socket: {vm['mountPath']}"})
risk = "CRITICAL" if any(f["severity"] == "CRITICAL" for f in findings) else \
"HIGH" if any(f["severity"] == "HIGH" for f in findings) else "MEDIUM"
return {"pod": pod_name, "namespace": namespace, "findings": findings, "risk": risk}
def main():
parser = argparse.ArgumentParser(description="K8s Pod PrivEsc Detector")
parser.add_argument("--namespace", default="--all-namespaces")
parser.add_argument("--json-file", help="Pod JSON file instead of kubectl")
args = parser.parse_args()
if args.json_file:
with open(args.json_file) as f:
data = json.load(f)
pods = data.get("items", [data]) if "items" in data else [data]
else:
pods = get_pods(args.namespace)
results = {"timestamp": datetime.utcnow().isoformat() + "Z", "pod_audits": []}
for pod in pods:
audit = audit_pod(pod)
if audit["findings"]:
results["pod_audits"].append(audit)
results["total_pods_with_issues"] = len(results["pod_audits"])
print(json.dumps(results, indent=2))
if __name__ == "__main__":
main()
process.py5.3 KB
Display-only source. This catalog never executes bundled scripts.
#!/usr/bin/env python3
"""
Kubernetes Privilege Escalation Scanner - Scan cluster for pods with
dangerous security configurations that enable privilege escalation.
"""
import json
import subprocess
import sys
import argparse
DANGEROUS_CAPS = {"SYS_ADMIN", "SYS_PTRACE", "SYS_MODULE", "DAC_OVERRIDE",
"NET_ADMIN", "NET_RAW", "SYS_RAWIO", "SYS_BOOT"}
def get_pods(namespace: str = None) -> list:
"""Get all pods from cluster."""
cmd = ["kubectl", "get", "pods", "-o", "json"]
if namespace:
cmd.extend(["-n", namespace])
else:
cmd.append("--all-namespaces")
result = subprocess.run(cmd, capture_output=True, text=True)
if result.returncode != 0:
print(f"Error: {result.stderr}", file=sys.stderr)
return []
return json.loads(result.stdout).get("items", [])
def check_pod_privesc(pod: dict) -> list:
"""Check a pod for privilege escalation risks."""
findings = []
name = pod["metadata"]["name"]
ns = pod["metadata"].get("namespace", "default")
spec = pod.get("spec", {})
# Host-level checks
if spec.get("hostPID"):
findings.append({"pod": name, "namespace": ns, "severity": "CRITICAL",
"finding": "hostPID enabled", "vector": "host-pid"})
if spec.get("hostNetwork"):
findings.append({"pod": name, "namespace": ns, "severity": "HIGH",
"finding": "hostNetwork enabled", "vector": "host-network"})
if spec.get("hostIPC"):
findings.append({"pod": name, "namespace": ns, "severity": "HIGH",
"finding": "hostIPC enabled", "vector": "host-ipc"})
# Volume checks
for vol in spec.get("volumes", []):
if vol.get("hostPath"):
path = vol["hostPath"].get("path", "")
findings.append({"pod": name, "namespace": ns, "severity": "HIGH",
"finding": f"hostPath volume: {path}", "vector": "host-path"})
# Container checks
for container in spec.get("containers", []) + spec.get("initContainers", []):
cname = container.get("name", "unknown")
sc = container.get("securityContext", {})
if sc.get("privileged"):
findings.append({"pod": name, "namespace": ns, "severity": "CRITICAL",
"finding": f"Container '{cname}' is privileged", "vector": "privileged"})
if sc.get("allowPrivilegeEscalation", True):
findings.append({"pod": name, "namespace": ns, "severity": "MEDIUM",
"finding": f"Container '{cname}' allows privilege escalation",
"vector": "allow-privesc"})
if sc.get("runAsUser") == 0:
findings.append({"pod": name, "namespace": ns, "severity": "HIGH",
"finding": f"Container '{cname}' runs as root (UID 0)",
"vector": "run-as-root"})
caps = sc.get("capabilities", {})
for cap in caps.get("add", []):
if cap in DANGEROUS_CAPS or cap == "ALL":
findings.append({"pod": name, "namespace": ns, "severity": "CRITICAL",
"finding": f"Container '{cname}' has dangerous cap: {cap}",
"vector": "dangerous-capability"})
return findings
def scan_cluster(namespace: str = None) -> list:
"""Scan entire cluster for privilege escalation risks."""
pods = get_pods(namespace)
all_findings = []
for pod in pods:
findings = check_pod_privesc(pod)
all_findings.extend(findings)
return all_findings
def print_report(findings: list):
"""Print scan report."""
if not findings:
print("No privilege escalation risks found.")
return
print(f"\n=== Kubernetes Privilege Escalation Scan ===")
print(f"Total findings: {len(findings)}\n")
severity_order = {"CRITICAL": 0, "HIGH": 1, "MEDIUM": 2, "LOW": 3}
findings.sort(key=lambda x: severity_order.get(x["severity"], 4))
print(f"{'Severity':<10} {'Namespace':<20} {'Pod':<35} {'Finding'}")
print("-" * 100)
for f in findings:
print(f"{f['severity']:<10} {f['namespace']:<20} {f['pod']:<35} {f['finding']}")
# Summary
from collections import Counter
by_sev = Counter(f["severity"] for f in findings)
print(f"\nSummary: CRITICAL={by_sev.get('CRITICAL',0)} HIGH={by_sev.get('HIGH',0)} "
f"MEDIUM={by_sev.get('MEDIUM',0)} LOW={by_sev.get('LOW',0)}")
def main():
parser = argparse.ArgumentParser(description="Kubernetes Privilege Escalation Scanner")
parser.add_argument("--namespace", "-n", help="Scan specific namespace")
parser.add_argument("--json", action="store_true", help="JSON output")
parser.add_argument("--fail-on", choices=["critical", "high", "medium"],
help="Exit non-zero if findings at threshold")
args = parser.parse_args()
findings = scan_cluster(args.namespace)
if args.json:
print(json.dumps(findings, indent=2))
else:
print_report(findings)
if args.fail_on:
threshold = {"critical": ["CRITICAL"], "high": ["CRITICAL", "HIGH"],
"medium": ["CRITICAL", "HIGH", "MEDIUM"]}
blocking = [f for f in findings if f["severity"] in threshold[args.fail_on]]
sys.exit(1 if blocking else 0)
if __name__ == "__main__":
main()
Assets 1
template.mdtext/markdown · 1.0 KBKeep exploring