Falco’s real power in Kubernetes isn’t just about catching bad guys; it’s about understanding the normal behavior of your cluster so you can spot the abnormal with surgical precision.
Let’s see it in action. Imagine you’re running a simple web application in Kubernetes.
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-webapp
spec:
replicas: 2
selector:
matchLabels:
app: my-webapp
template:
metadata:
labels:
app: my-webapp
spec:
containers:
- name: webapp-container
image: nginx:latest
ports:
- containerPort: 80
Now, let’s say Falco is running in your cluster, configured with a basic set of rules. If someone tries to exec into one of these pods without authorization, Falco will flag it.
Here’s a simplified Falco rule that would catch this:
- rule: Execute command in container
desc: "Detects execution of a shell or command interpreter inside a container."
condition: container and proc.name in ("sh", "bash", "zsh", "ash")
output: "Shell or interpreter executed in container (user: %user.name, login: %user.login, cmd: %proc.cmdline, pid: %proc.pid, container: %container.name, image: %container.image)"
priority: WARNING
When that rule fires, you’ll see an alert like this in your Falco output (e.g., to stdout, a file, or a SIEM):
{
"output": "01:00:00.123456789 - Warning - Shell or interpreter executed in container (user: kubectl, login: root, cmd: /bin/sh, pid: 1234, container: my-webapp-abcdef-12345, image: nginx:latest)",
"priority": "Warning",
"rule": "Execute command in container",
"time": "2023-10-27T10:00:00.123456789Z",
"source": "syscall",
"nodename": "worker-node-1",
"kubernetes": {
"container": {
"id": "abcdef1234567890abcdef1234567890abcdef1234567890abcdef12345",
"name": "my-webapp-abcdef-12345",
"image": "nginx:latest"
},
"pod": {
"name": "my-webapp-abcdef-12345",
"namespace": "default"
},
"node": {
"name": "worker-node-1"
}
},
"proc": {
"pid": 1234,
"name": "sh",
"cmdline": "/bin/sh"
},
"user": {
"name": "kubectl",
"login": "root"
}
}
This alert tells you exactly what happened: a shell was executed (/bin/sh) inside the my-webapp-abcdef-12345 container by a user named kubectl. This is your signal that something is likely amiss.
Beyond simple command execution, Falco excels at detecting suspicious network activity. Imagine a pod that’s supposed to only talk to your internal database suddenly trying to reach an external IP address. Falco can monitor outbound connections and alert you.
Consider a rule for detecting outbound connections to unexpected IP ranges:
- rule: Unexpected outbound connection
desc: "Detects outbound network connection to an IP outside of known internal ranges."
condition: outbound and net.dest_ip !~ "10.0.0.0/8" and net.dest_ip !~ "192.168.0.0/16"
output: "Unexpected outbound connection to %net.dest_ip:%net.dest_port from container %container.name (image: %container.image)"
priority: CRITICAL
This rule uses Falco’s outbound macro and checks if the destination IP address falls outside your defined internal network CIDRs. If a pod in your default namespace suddenly tries to connect to 8.8.8.8, Falco will fire:
{
"output": "Unexpected outbound connection to 8.8.8.8:53 from container my-webapp-abcdef-12345 (image: nginx:latest)",
"priority": "Critical",
"rule": "Unexpected outbound connection",
"time": "2023-10-27T10:05:00.987654321Z",
"source": "syscall",
"nodename": "worker-node-1",
"kubernetes": {
"container": {
"id": "abcdef1234567890abcdef1234567890abcdef1234567890abcdef12345",
"name": "my-webapp-abcdef-12345",
"image": "nginx:latest"
},
"pod": {
"name": "my-webapp-abcdef-12345",
"namespace": "default"
},
"node": {
"name": "worker-node-1"
}
},
"net": {
"dest_ip": "8.8.8.8",
"dest_port": 53
}
}
Another critical use case is privilege escalation and unauthorized file access. If a container process, which should have limited privileges, suddenly tries to write to sensitive system directories or execute as root, Falco can catch it.
A rule to detect writing to sensitive directories:
- rule: Write to sensitive directory
desc: "Detects writing to sensitive system directories."
condition: evt.type = "open" and evt.dir in ("/etc", "/root", "/var/run/secrets") and fd.flags contains "O_WRONLY"
output: "Write attempt to sensitive directory %evt.dir (file: %fd.name, container: %container.name, image: %container.image)"
priority: CRITICAL
This rule monitors open syscalls where the directory is sensitive (like /etc or /root) and the file is opened for writing. If a container attempts to modify /etc/passwd, Falco would alert:
{
"output": "Write attempt to sensitive directory /etc (file: passwd, container: my-webapp-abcdef-12345, image: nginx:latest)",
"priority": "Critical",
"rule": "Write to sensitive directory",
"time": "2023-10-27T10:10:00.112233445Z",
"source": "syscall",
"nodename": "worker-node-1",
"kubernetes": {
"container": {
"id": "abcdef1234567890abcdef1234567890abcdef1234567890abcdef12345",
"name": "my-webapp-abcdef-12345",
"image": "nginx:latest"
},
"pod": {
"name": "my-webapp-abcdef-12345",
"namespace": "default"
},
"node": {
"name": "worker-node-1"
}
},
"evt": {
"type": "open",
"dir": "/etc"
},
"fd": {
"name": "passwd"
}
}
You can also use Falco to detect container escape attempts. This often involves processes within a container trying to access the host’s filesystem or interact with the Docker daemon socket.
A rule might look for the Docker socket being accessed from within a pod:
- rule: Access to Docker socket
desc: "Detects access to the Docker socket from within a container."
condition: container and proc.name = "docker" and fd.name = "/var/run/docker.sock"
output: "Docker socket accessed from container (process: %proc.name, cmd: %proc.cmdline, container: %container.name, image: %container.image)"
priority: CRITICAL
The real magic of Falco lies in its ability to correlate events. It doesn’t just see a single syscall; it sees that syscall in the context of the container, the pod, the Kubernetes namespace, and the node it’s running on. This rich context is what allows you to build highly specific and effective detection rules.
What most people miss is that Falco’s strength is in defining "normal" for your specific Kubernetes environment. Instead of writing blanket rules that generate endless noise, you can tailor Falco to understand what your pods should be doing, what network connections they should be making, and what files they should be accessing. This baseline of normalcy is then used to pinpoint deviations that indicate a potential threat.
Once you’ve mastered these core detection use cases, you’ll naturally want to explore how to integrate Falco alerts into your incident response workflows, perhaps by triggering automated remediation actions or enriching security tickets.