Docker Runtime Security: Detect Abnormal System Calls with Falco and eBPF

Traditional security scanners find vulnerabilities in your images before deployment, but they are blind to what happens once a container starts running. If an attacker exploits a 0-day vulnerability to spawn a reverse shell or modify sensitive files like /etc/shadow, your static analysis won't help. You need a way to monitor the heartbeat of your operating system—the system calls—to identify malicious intent as it happens. By integrating Falco with the Linux kernel's eBPF (Extended Berkeley Packet Filter) technology, you gain a deep-level security camera that monitors every action inside your Docker containers without modifying the containers themselves. This guide shows you how to implement real-time detection for unauthorized binary executions and privilege escalations. TL;DR — Falco taps into the Linux kernel via eBPF to monitor system calls. It matches these calls against a library of security rules and triggers alerts whenever a container behaves abnormally, such as executing a shell or writing to a binary directory.

Table of Contents

Understanding Falco and eBPF

Falco functions as a runtime security engine. Unlike an Intrusion Detection System (IDS) that looks at network packets, Falco looks at system calls (syscalls). Every time a process wants to read a file, open a network connection, or spawn a child process, it must ask the Linux kernel via a syscall.
💡 Analogy: Imagine your Linux kernel is a high-security bank vault. Every person (process) must speak to the clerk (Kernel) to do anything. Falco is the security guard standing next to the clerk, listening to every request. If someone asks for a "sledgehammer" (malicious syscall) instead of a "pen," the guard pulls the alarm.
Using the eBPF driver is the modern way to run Falco. While older versions relied on kernel modules that could crash the host, eBPF runs in a protected sandbox within the kernel. It provides high-performance data collection with minimal risk to host stability. This allows you to monitor thousands of containers on a single host with negligible overhead.

When to Use Runtime Detection

You should implement Falco in the following scenarios:
  1. Detecting Drift: When you want to ensure your "immutable" containers aren't being modified after launch (e.g., someone installing curl or git inside a running production container).
  2. Compliance Requirements: If you need to meet SOC2 or PCI-DSS standards that require monitoring for unauthorized access to sensitive system files.
  3. Zero-Day Mitigation: When a new exploit appears (like Log4Shell), Falco can detect the resulting behavior—such as a Java process spawning a shell—even if your scanners haven't updated their signatures yet.

Step-by-Step Implementation

Step 1: Install Falco with eBPF Support

First, ensure your host has a Linux kernel version 5.8 or higher for optimal eBPF support. Use the official script to install Falco on your host.
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
sudo apt-get install -y falco

Step 2: Configure the eBPF Driver

Switch from the default kernel module to the eBPF probe. Edit the configuration file or use the command line to trigger the eBPF engine.
# Change the engine in /etc/falco/falco.yaml
driver:
kind: ebpf
ebpf:
probe: /root/.falco/falco-bpf.o

Step 3: Create a Custom Security Rule

Let's create a rule that alerts us whenever someone executes a shell inside a Docker container. Create a file at /etc/falco/falco_rules.local.yaml.
- rule: Terminal shell in container
desc: A shell was used as the entrypoint or started in a container
condition: >
container.id != host and
proc.name in (shell_binaries) and
container.image.repository != "trusted/admin-tools"
output: >
Unauthorized shell spawned (user=%user.name container_id=%container.id
image=%container.image.repository shell=%proc.name parent=%proc.pname cmdline=%proc.cmdline)
priority: WARNING

Step 4: Restart and Test

Restart the service and simulate an attack by executing docker exec -it [container_id] sh.
sudo systemctl restart falco
# Check the logs for the alert
sudo journalctl -fu falco

Common Pitfalls and Troubleshooting

⚠️ Common Mistake: Missing Kernel Headers
Falco needs kernel headers to compile the eBPF probe on the fly. If you see the error "Unable to load the driver," you are likely missing these headers.
To fix this, install the headers matching your current kernel:
sudo apt-get install linux-headers-$(uname -r)
Another issue is CPU Spike. If your server handles 100,000+ syscalls per second (common in high-traffic databases), Falco might consume significant CPU. You must use the modern-ebpf engine available in Falco 0.35+ which uses ring buffers to reduce overhead, or refine your rules to ignore noisy, trusted processes.

Optimization and Summary

To keep your runtime security efficient, follow these tips:
  • Macro Usage: Use Falco "macros" to group trusted images so your rules remain clean and maintainable.
  • Output Sidekicks: Don't just rely on local logs. Use Falcosidekick to send alerts to Slack, Datadog, or an S3 bucket for long-term auditing.
  • Prioritize: Start with "Critical" and "Error" priority rules to avoid alert fatigue.
📌 Key Takeaways
  • Falco provides visibility into container internals via kernel syscalls.
  • eBPF is the preferred driver for stability and security.
  • Custom rules allow you to whitelist specific administrative actions while blocking attackers.
  • Monitoring runtime is the only way to catch 0-day post-exploitation activity.

Frequently Asked Questions

Q. Does Falco block malicious actions automatically?

A. No. Falco is a detection tool, not an enforcement tool. It alerts you. To block actions, you need Falco Talon or AppArmor/SELinux profiles.

Q. What is the performance impact of using eBPF?

A. Usually under 1-3% CPU overhead. It varies based on the number of system calls and the complexity of your rule set.

Q. Can Falco monitor Kubernetes clusters?

A. Yes. Falco is often deployed as a DaemonSet in Kubernetes to monitor every node and provide K8s-specific metadata like Pod names and Namespaces.

Post a Comment