In 2024, attackers exploiting CVE-2024-1086 — a Linux netfilter use-after-free — dropped rootkits that blinded traditional auditd logging within seconds of execution. The defenders who caught it fastest weren’t relying on log files. They were running eBPF-based probes that observed kernel behavior in real time, before the rootkit could tamper with userspace tooling.
eBPF (extended Berkeley Packet Filter) lets you attach small, sandboxed programs directly to kernel hooks — syscalls, network events, file operations — with near-zero overhead. No kernel modules. No reboots. Just visibility.
Example 1: Catching Privilege Escalation with bpftrace
bpftrace is a high-level tracing language for eBPF — think awk, but for the Linux kernel. You write one-liners or short scripts that attach to kernel probes and stream events to your terminal.
Here’s a one-liner that watches every setuid() call system-wide and prints the process name, PID, and the UID it’s trying to set:
sudo bpftrace -e '
tracepoint:syscalls:sys_enter_setuid
{
printf("%s PID: %d new_uid: %d\n",
comm, pid, args->uid);
}'
On a clean host, you’ll see almost nothing. On prod-web-01.internal (192.0.2.14) during an active attack, you might see output like this:
bash PID: 4821 new_uid: 0
python3 PID: 4822 new_uid: 0
sh PID: 4823 new_uid: 0
Three processes hammering setuid(0) in rapid succession is a textbook post-exploitation pattern — an attacker has a foothold as user deploy and is running a local privilege escalation chain. The python3 entry is the tell: legitimate app code rarely calls setuid directly.
Your next move: cross-reference PID 4822 with ls -la /proc/4822/exe and cat /proc/4822/cmdline to find the binary and its arguments without touching disk-based logs the attacker may have already poisoned.
Example 2: Real-Time Threat Detection with Falco
Falco is a CNCF security tool that uses eBPF (or a kernel module) to enforce rules against live kernel events. It’s the difference between writing your own probes and having a curated ruleset maintained by a security community.
Install the eBPF driver version and start Falco on your host:
sudo falco --modern-bpf -r /etc/falco/falco_rules.yaml 2>&1 | grep -v DEBUG
Simulate a classic attacker move — reading /etc/shadow as a non-root user via a SUID binary abuse — and Falco fires immediately:
2026-09-25T11:42:07.381Z CRITICAL Sensitive file opened for reading by non-trusted program
proc.name=python3 proc.pid=5109
user.name=deploy user.uid=1002
fd.name=/etc/shadow
container.id=host
rule=Read sensitive file untrusted
Falco gives you the process name, the user, the exact file, and the rule that fired — all within milliseconds of the open syscall. The user here is deploy (UID 1002), which should never be reading /etc/shadow. This is not a false positive you investigate tomorrow. This is a page-now event.
What you do next depends on your response playbook. A common automated response: Falco’s output feeds into a webhook that triggers an Ansible playbook to isolate 192.0.2.14 at the firewall level and snapshot its memory with avml for forensics — all before the attacker finishes their next command.
Tuning eBPF Monitoring Without Drowning in Noise
Raw eBPF visibility is powerful but noisy. Here’s how practitioners keep signal high:
- Baseline first. Run bpftrace or Falco in log-only mode for 48 hours before alerting. Know what normal looks like on your specific workload.
- Scope your probes. Don’t watch every syscall — watch the ones that matter:
execve,setuid,ptrace,openaton sensitive paths, andconnectfor unexpected outbound calls. - Layer with context. eBPF gives you kernel events. Combine them with process ancestry (
proc.pnamein Falco) so you can distinguishsshdspawning a shell legitimately versus a web process doing the same thing suspiciously. - Suppress known-good. Add Falco macros to whitelist your backup agent, your monitoring tools, and your CI runners. Every suppressed known-good alert is bandwidth for real threats.
One pattern worth building early: a bpftrace script that logs every new outbound connect() call with the destination IP and the process tree. Lateral movement almost always touches the network. Catching an unexpected python3 connecting to 192.0.2.88 on port 4444 from a web server process is the kind of early warning that changes incident outcomes.
What To Do Now
Pick one production Linux host — not a lab, a real host — and run this bpftrace one-liner for 60 seconds:
sudo bpftrace -e '
tracepoint:syscalls:sys_enter_execve
{
printf("%s PID: %d PPID: %d args: %s\n",
comm, pid, curtask->real_parent->tgid, str(args->filename));
}'
Every process execution, its parent, and the binary path — live. Scroll through the output and ask yourself: does everything here look expected? If you spot a sh or curl spawned by your web server process, you already have a lead worth pulling. That’s eBPF security monitoring in practice: not a dashboard, not a report — a live window into what your kernel is actually doing right now.
