Skills Engineering Detecting Container Runtime Threats with Falco

Detecting Container Runtime Threats with Falco

v20260622
detecting-container-runtime-threats-with-falco
Falco is a powerful CNCF project for real-time runtime security monitoring. This guide teaches authors how to write and deploy custom detection rules using Falco's robust YAML rule engine and modern eBPF driver. It is designed to detect critical threats such as container escapes, namespace manipulation, privileged mounts, and anomalous syscalls in Kubernetes and Docker environments, significantly hardening the overall container security posture.
Get Skill
58 downloads
Overview

Detecting Container Runtime Threats with Falco

Overview

Falco is the CNCF graduated runtime-security project (originally by Sysdig) that consumes Linux kernel syscalls and Kubernetes audit events through a driver, evaluates them against a YAML rule engine, and emits real-time alerts. It is the de facto open-source detection tool for runtime threats inside containers, including container escape (MITRE ATT&CK T1611, Escape to Host), namespace manipulation (setns), privileged mounts, reverse shells, and unexpected outbound connections.

Falco supports three drivers: the modern eBPF probe (preferred default, requires kernel >= 5.8, shipped directly inside the Falco binary so no init container is needed), the legacy eBPF probe, and the kernel module (kmod). Driver selection is handled by falcoctl driver config --type {kmod|ebpf|modern_ebpf} or driver.kind=modern_ebpf in the Helm chart. On Kubernetes, Falco runs as a DaemonSet so every node is monitored, and falcoctl automatically installs and updates rule artifacts from the Falco rules registry.

This skill covers authoring and deploying custom Falco rules to detect the container-escape primitives and anomalous-behavior signals that the breakout techniques in this collection produce. Each Falco rule has the fields rule, desc, condition, output, priority, and optional tags; reusable logic is factored into macro and list objects. Source: falco.org official documentation; falcosecurity/rules repository; Sysdig Falco detection research (e.g., CVE-2025-22224).

When to Use

  • Building runtime detections for a Kubernetes or Docker environment
  • Validating that container-escape and lateral-movement attempts generate alerts (purple-team)
  • Adding coverage for a newly disclosed runtime CVE
  • Hardening a SOC's container telemetry pipeline (Falco -> Falcosidekick -> SIEM)

Prerequisites

  • A Linux host (kernel >= 5.8 for modern eBPF) or Kubernetes cluster you administer
  • Falco install:
    # Helm (Kubernetes, modern eBPF, JSON output for SIEM ingest)
    helm repo add falcosecurity https://falcosecurity.github.io/charts
    helm repo update
    helm install falco falcosecurity/falco \
      --namespace falco --create-namespace \
      --set driver.kind=modern_ebpf \
      --set collectors.containerd.enabled=true \
      --set falco.json_output=true \
      --set tty=true
    
    # Linux package install (Debian/Ubuntu)
    curl -fsSL https://falco.org/repo/falcosecurity-packages.asc | \
      sudo gpg --dearmor -o /usr/share/keyrings/falco-archive-keyring.gpg
    echo "deb [signed-by=/usr/share/keyrings/falco-archive-keyring.gpg] \
      https://download.falco.org/packages/deb stable main" | \
      sudo tee /etc/apt/sources.list.d/falcosecurity.list
    sudo apt-get update -y && sudo apt-get install -y falco
    
  • Basic familiarity with Falco fields (evt.type, proc.name, container.id, fd.name)

Objectives

  • Install Falco with the modern eBPF driver
  • Understand the rule/macro/list schema and key Falco filter fields
  • Author custom rules for container escape, setns, privileged mounts, sensitive-file reads, and reverse shells
  • Load custom rules and validate syntax
  • Trigger and confirm detections (purple-team validation)
  • Forward alerts to a SIEM via Falcosidekick

MITRE ATT&CK Mapping

Technique ID Name Tactic
T1611 Escape to Host Privilege Escalation
T1059.004 Command and Scripting Interpreter: Unix Shell Execution
T1610 Deploy Container Defense Evasion / Execution
T1543 Create or Modify System Process Persistence
T1071.001 Application Layer Protocol: Web Protocols Command and Control

Workflow

Step 1: Install Falco and Confirm the Driver

# Kubernetes: confirm the DaemonSet is running on every node
kubectl get pods -n falco -o wide
kubectl logs -n falco -l app.kubernetes.io/name=falco | grep -i "driver"

# Linux host: configure driver and start
sudo falcoctl driver config --type modern_ebpf
sudo systemctl enable --now falco-modern-bpf.service
sudo systemctl status falco-modern-bpf.service

Step 2: Learn the Rule, Macro, and List Schema

Custom rules live in /etc/falco/falco_rules.local.yaml or /etc/falco/rules.d/, referenced from rules_files in /etc/falco/falco.yaml.

# /etc/falco/rules.d/custom-escape.yaml
- list: shell_binaries
  items: [bash, sh, zsh, dash, ash, ksh]

- macro: spawned_process
  condition: evt.type in (execve, execveat) and evt.dir = <

- macro: container
  condition: container.id != host

Step 3: Write a Container-Escape Detection Rule (release_agent / cgroup)

- rule: Container Escape via cgroup release_agent
  desc: >
    Detect a process inside a container writing to a cgroup release_agent or
    notify_on_release file, a classic privileged-container breakout primitive.
  condition: >
    container
    and spawned_process
    and (evt.type in (open, openat, openat2) or evt.type=write)
    and (fd.name endswith "release_agent"
         or fd.name endswith "notify_on_release")
    and evt.is_open_write=true
  output: >
    Container escape attempt via cgroup release_agent
    (user=%user.name command=%proc.cmdline file=%fd.name
     container=%container.name image=%container.image.repository)
  priority: CRITICAL
  tags: [container, mitre_privilege_escalation, T1611]

Step 4: Detect Namespace Breakout (setns / nsenter)

- rule: Namespace Change via setns to Host
  desc: >
    Detect setns/nsenter used to enter the host namespace (e.g. nsenter -t 1),
    a common container-to-host escape technique.
  condition: >
    evt.type = setns
    and container
    and proc.name in (nsenter, unshare)
  output: >
    Namespace breakout via setns/nsenter
    (user=%user.name proc=%proc.name cmd=%proc.cmdline
     container=%container.name image=%container.image.repository)
  priority: CRITICAL
  tags: [container, mitre_privilege_escalation, T1611]

Step 5: Detect Privileged Mount and Docker Socket Abuse

- rule: Mount Launched in Privileged Container
  desc: Detect the mount binary running inside a privileged container.
  condition: >
    spawned_process
    and container
    and container.privileged = true
    and proc.name = mount
  output: >
    Mount executed in privileged container
    (cmd=%proc.cmdline container=%container.name image=%container.image.repository)
  priority: WARNING
  tags: [container, mitre_privilege_escalation, T1611]

- rule: Docker Socket Accessed From Container
  desc: A container process reads/writes the host Docker daemon socket.
  condition: >
    container
    and (evt.type in (open, openat, openat2, connect))
    and fd.name = /var/run/docker.sock
  output: >
    Container touched docker.sock - possible daemon-API escape
    (proc=%proc.name cmd=%proc.cmdline container=%container.name)
  priority: CRITICAL
  tags: [container, mitre_execution, T1610]

Step 6: Detect Reverse Shells and Sensitive File Reads

- rule: Reverse Shell From Container
  desc: A shell in a container with stdin/stdout wired to a network socket.
  condition: >
    spawned_process
    and container
    and proc.name in (shell_binaries)
    and (fd.num in (0, 1, 2))
    and fd.type in (ipv4, ipv6)
  output: >
    Reverse shell detected in container
    (proc=%proc.cmdline connection=%fd.name container=%container.name)
  priority: CRITICAL
  tags: [container, mitre_execution, T1059.004]

- rule: Read Sensitive Host File From Container
  desc: Container reads /etc/shadow or similar after a likely escape.
  condition: >
    container
    and (evt.type in (open, openat, openat2))
    and evt.is_open_read=true
    and fd.name in (/etc/shadow, /etc/sudoers, /root/.ssh/id_rsa)
  output: >
    Sensitive file read from container (file=%fd.name proc=%proc.cmdline
     container=%container.name)
  priority: WARNING
  tags: [container, mitre_credential_access]

Step 7: Validate Rule Syntax and Load

# Dry-run validate a rules file without starting the engine
sudo falco --validate /etc/falco/rules.d/custom-escape.yaml

# Run Falco with only the custom rules to test
sudo falco -r /etc/falco/rules.d/custom-escape.yaml

# Helm: ship custom rules via values (mounted into /etc/falco/rules.d)
helm upgrade falco falcosecurity/falco -n falco --reuse-values \
  --set-file "customRules.custom-escape\.yaml"=./custom-escape.yaml

Step 8: Trigger and Confirm (Purple-Team)

# In a test container, trigger the setns rule
kubectl run pwn --rm -it --image=alpine --overrides='
{"spec":{"hostPID":true,"containers":[{"name":"pwn","image":"alpine",
"securityContext":{"privileged":true},"stdin":true,"tty":true,
"command":["sh"]}]}}' -- sh -c 'nsenter -t 1 -m -u -i -n -p -- id'

# Confirm the alert fired
kubectl logs -n falco -l app.kubernetes.io/name=falco | grep -i "Namespace breakout"

Step 9: Forward Alerts to a SIEM

# Deploy Falcosidekick to fan out alerts (Elastic, Slack, Splunk, etc.)
helm upgrade falco falcosecurity/falco -n falco --reuse-values \
  --set falcosidekick.enabled=true \
  --set falcosidekick.config.elasticsearch.hostport=https://elastic:9200 \
  --set falcosidekick.config.elasticsearch.index=falco

Tools and Resources

Tool Purpose Source
Falco Runtime syscall detection engine https://falco.org
falcoctl Driver + rules artifact manager https://github.com/falcosecurity/falcoctl
falcosecurity/rules Maintained default ruleset https://github.com/falcosecurity/rules
Falcosidekick Alert fan-out to SIEM/chat https://github.com/falcosecurity/falcosidekick
Falco Helm chart Kubernetes DaemonSet deploy https://github.com/falcosecurity/charts

Key Falco Filter Fields

Field Meaning
evt.type Syscall name (execve, setns, open, connect)
evt.dir Event direction (< exit, > enter)
proc.name / proc.cmdline Process name / full command line
container.id / container.privileged Container identity / privileged flag
container.image.repository Image name
fd.name / fd.type File/socket path / type (ipv4, ipv6)
evt.is_open_write / evt.is_open_read Open intent
user.name Acting user

Validation Criteria

  • Falco installed with the modern eBPF driver (DaemonSet on all nodes)
  • Custom rules file validated with falco --validate
  • release_agent / setns / privileged-mount / docker.sock rules loaded
  • Reverse-shell and sensitive-file-read rules loaded
  • Each rule triggered in a lab and the alert confirmed in logs
  • Priorities set appropriately (CRITICAL for escape primitives)
  • Alerts forwarded to the SIEM via Falcosidekick
  • Rule tags include the relevant MITRE technique IDs
Info
Category Engineering
Name detecting-container-runtime-threats-with-falco
Version v20260622
Size 12.9KB
Updated At 2026-06-26
Language