Uvod u eBPF - revolucija u sigurnosti Linux jezgre
Zamislite da možete umetnuti prilagođeni sigurnosni kod izravno u jezgru Linuxa — bez ponovnog prevođenja, bez nestabilnih modula, bez restarta. Zvuči predobro da bi bilo istinito? Pa, upravo to omogućuje eBPF (extended Berkeley Packet Filter). Radi se o tehnologiji koja je doslovno promijenila pravila igre kad govorimo o sigurnosnom nadzoru, detekciji prijetnji i primjeni politika na Linux sustavima.
Malo povijesti. Izvorna BPF tehnologija nastala je 1992. na Sveučilištu u Berkeleyu kao jednostavan mehanizam za filtriranje mrežnih paketa. Svrha joj je bila omogućiti učinkovito izvršavanje pravila filtriranja u jezgrenom prostoru, izbjegavajući skupo kopiranje svakog paketa u korisnički prostor. Alati poput tcpdump koristili su klasični BPF desetljećima, no funkcionalnost je bila ograničena isključivo na mrežni sloj.
Prijelomni trenutak nastupio je između 2014. i 2016. godine. Alexei Starovoitov, uz potporu Daniela Borkmanna, predstavio je extended BPF u Linux jezgru 3.18+. Nova arhitektura donijela je 64-bitne registre, prošireni skup instrukcija, pristup jezgrenim strukturama podataka i mogućnost priključivanja na gotovo bilo koju točku u jezgri. Od jednostavnog filtra paketa, eBPF je prerastao u potpunu virtualnu mašinu unutar jezgre — s mogućnostima koje sežu daleko izvan mrežnog sloja. Praćenje performansi, dijagnostika, i ono što nas ovdje najviše zanima — napredna sigurnost.
Danas je eBPF temelj modernih sigurnosnih rješenja poput Cilium Tetragona, Falca i Tracee-a. U ovom vodiču detaljno ćemo proći arhitekturu eBPF-a, integraciju s Linux Security Modules (LSM), praktične primjere sigurnosnog nadzora, najvažnije alate te rizike koje donosi ova moćna tehnologija.
Arhitektura eBPF-a - kako funkcionira sigurnosna platforma unutar jezgre
Bez razumijevanja arhitekture nema smisla uopće kretati u implementaciju. Dakle, hajdemo raščlaniti kako eBPF zapravo radi. U suštini, radi se o izoliranoj virtualnoj mašini unutar Linux jezgre koja omogućuje izvršavanje korisničkog koda na siguran i kontroliran način.
Verifikator (Verifier)
Prije nego što se bilo koji eBPF program učita u jezgru, prolazi kroz strogi proces verifikacije. Verifikator provodi statičku analizu bajtkoda i osigurava:
- Acikličnost kontrolnog toka — program ne smije sadržavati beskonačne petlje (osim ograničenih petlji s poznatim brojem iteracija)
- Sigurnost memorije i tipova — svaki pristup memoriji mora biti unutar dozvoljenih granica
- Valjanost poziva pomoćnih funkcija — program smije koristiti samo odobrene jezgrene helper funkcije
- Odsutnost curenja informacija — spriječava neželjeno prenošenje jezgrenih podataka u korisnički prostor
- Sigurnost resursa — nema neuravnoteženih zaključavanja ili brojača referenci
- Zajamčen završetak — program mora garantirano završiti u konačnom vremenu
Verifikator je prva i najvažnija linija obrane. Bez njega, svaki loše napisan (ili namjerno zlonamjeran) eBPF program mogao bi srušiti cijelu jezgru.
JIT prevodilac (Just-In-Time Compiler)
Nakon uspješne verifikacije, eBPF bajtkod prolazi kroz JIT prevodilac koji ga pretvara u strojni kod specifičan za arhitekturu procesora (x86_64, ARM64 itd.). Rezultat? Izvršavanje gotovo istom brzinom kao nativni jezgreni kod. To je ključno za sigurnosne aplikacije gdje svaka mikrosekunda kašnjenja može biti problem.
Mape (Maps)
eBPF mape su strukture podataka ključ-vrijednost koje služe kao dijeljeni memorijski prostor između eBPF programa u jezgrenom prostoru i aplikacija u korisničkom prostoru. Sigurnosni alati ih koriste za:
- Pohranu konfiguracije sigurnosnih politika
- Razmjenu informacija o detektiranim prijetnjama
- Održavanje stanja između različitih poziva eBPF programa
- Agregaciju statistika i metrika sigurnosnih događaja
Priključne točke (Hooks)
eBPF programi se priključuju na unaprijed definirane točke u jezgri. Za sigurnost su posebno bitne ove:
- Tracepoints — statičke točke instrumentacije u jezgri
- Kprobes/Kretprobes — dinamičko praćenje jezgrenih funkcija na ulazu i izlazu
- LSM hooks — priključne točke Linux Security Modules okvira
- Syscall hooks — praćenje sustavskih poziva
- XDP (eXpress Data Path) — obrada mrežnih paketa na najnižoj razini
Jezgreni prostor naspram korisničkog prostora
I evo ključne prednosti. S eBPF-om, filtriranje i obrada odvijaju se izravno u jezgrenom prostoru. Tradicionalni sigurnosni alati morali su kopirati sve događaje u korisnički prostor za analizu — a to znači značajno kašnjenje i opterećenje sustava. eBPF mijenja tu igru: sofisticirana logika filtriranja pa čak i aktivno provođenje politika izvršavaju se unutar jezgre, a u korisnički prostor šalju se samo relevantni, obogaćeni događaji.
eBPF LSM (Linux Security Module) - sigurnosna kontrola na razini jezgre
Linux jezgra 5.7, objavljena u lipnju 2020., donijela je jednu od najznačajnijih sigurnosnih inovacija — BPF LSM. Ova značajka omogućuje priključivanje eBPF programa na LSM priključne točke, čime se otvaraju vrata za pisanje dinamičkih, granularnih sigurnosnih politika bez modificiranja jezgre ili učitavanja tradicionalnih modula.
Što je BPF_PROG_TYPE_LSM?
Kada se eBPF program učitava s tipom BPF_PROG_TYPE_LSM, jezgra ga tretira kao sigurnosni modul. Program se priključuje na jednu od stotina dostupnih LSM priključnih točaka i izvršava se svaki put kad se dogodi odgovarajuća zaštićena operacija — otvaranje datoteke, stvaranje mrežne utičnice, izvršavanje binarnog programa i slično.
Ponašanje je definirano povratnom vrijednošću:
- Povratna vrijednost
0— operacija je dozvoljena - Negativna vrijednost (npr.
-EPERM) — operacija je odbijena
Jednostavno, zar ne?
Provjera podrške za BPF LSM
Prije nego krenete koristiti BPF LSM, provjerite je li jezgra ispravno konfigurirana:
# Provjera je li CONFIG_BPF_LSM omogućen u jezgri
cat /boot/config-$(uname -r) | grep BPF_LSM
# Očekivani rezultat:
# CONFIG_BPF_LSM=y
# Provjera aktivnih LSM modula
cat /sys/kernel/security/lsm
# Provjera je li BPF u listi LSM modula
cat /proc/cmdline | grep bpf
Omogućavanje BPF LSM-a
Ako BPF LSM nije aktiviran, morate ga dodati u parametre pokretanja jezgre:
# Uređivanje GRUB konfiguracije
sudo nano /etc/default/grub
# Dodati 'bpf' u LSM listu:
GRUB_CMDLINE_LINUX="lsm=lockdown,capability,yama,apparmor,bpf"
# Ažuriranje GRUB-a i ponovno pokretanje
sudo update-grub
sudo reboot
Praktični primjer: blokiranje stvaranja mrežnih utičnica
Evo jednog konkretnog primjera. Sljedeći eBPF LSM program blokira stvaranje RAW utičnica, čime se sprječavaju neovlašteni pokušaji mrežnog skeniranja:
// deny_raw_socket.bpf.c
#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>
#include <linux/errno.h>
// LSM hook za socket_create
SEC("lsm/socket_create")
int BPF_PROG(deny_raw_socket, int family, int type, int protocol, int kern)
{
// Dozvoli jezgrene utičnice
if (kern)
return 0;
// Blokiraj RAW utičnice iz korisničkog prostora
if (type == 3) { // SOCK_RAW = 3
bpf_printk("Blokiran pokušaj stvaranja RAW utičnice: family=%d
", family);
return -EPERM;
}
return 0;
}
char LICENSE[] SEC("license") = "GPL";
Primjer: ograničavanje pristupa osjetljivim datotekama
// deny_sensitive_file.bpf.c
#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
#include <linux/errno.h>
SEC("lsm/file_open")
int BPF_PROG(restrict_file_open, struct file *file)
{
const char *filename;
char buf[256];
filename = BPF_CORE_READ(file, f_path.dentry, d_name.name);
bpf_probe_read_kernel_str(buf, sizeof(buf), filename);
// Blokiraj pristup shadow datoteci iz neprivilegiranih procesa
if (buf[0] == 's' && buf[1] == 'h' && buf[2] == 'a' &&
buf[3] == 'd' && buf[4] == 'o' && buf[5] == 'w') {
__u32 uid = bpf_get_current_uid_gid() & 0xFFFFFFFF;
if (uid != 0) {
bpf_printk("Blokiran pristup shadow datoteci od UID: %d
", uid);
return -EPERM;
}
}
return 0;
}
char LICENSE[] SEC("license") = "GPL";
Praktični primjeri sigurnosnog nadzora s eBPF-om
Dosta teorije — prijeđimo na praksu. eBPF pruža bogat ekosustav alata za sigurnosni nadzor, a u ovom odjeljku fokusirat ćemo se na konkretne primjere korištenja bpftool i drugih alata.
Korištenje bpftool za inspekciju eBPF programa
bpftool je, iskreno, neizostavni alat za svakoga tko ozbiljno radi s eBPF-om. Evo najvažnijih naredbi za sigurnosnu analizu:
# Izlistavanje svih učitanih eBPF programa
sudo bpftool prog list
# Primjer izlaza:
# 6: cgroup_skb tag 6deef7357e7b4530 gpl
# loaded_at 2024-01-15T10:23:45+0100 uid 0
# xlated 296B jited 209B memlock 4096B
# 27: lsm name restrict_open tag a1b2c3d4e5f6
# loaded_at 2024-01-15T14:30:00+0100 uid 0
# xlated 512B jited 384B memlock 4096B
# Detaljni prikaz specifičnog programa
sudo bpftool prog show id 27 --pretty
# Izlistavanje svih eBPF mapa
sudo bpftool map list
# Pregled sadržaja specifične mape
sudo bpftool map dump id 5
# Prikaz programa priključenih na specifične priključne točke
sudo bpftool perf list
# Izvoz programa u JSON format za daljnju analizu
sudo bpftool prog list --json | python3 -m json.tool
Nadzor sustavskih poziva (syscall monitoring)
Praćenje sustavskih poziva jedna je od ključnih tehnika za detekciju sumnjivog ponašanja. Sljedeći primjer prati pozive execve — čest indikator zlonamjerne aktivnosti:
// monitor_exec.bpf.c
#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
struct event {
__u32 pid;
__u32 uid;
char comm[16];
char filename[256];
};
struct {
__uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
__uint(key_size, sizeof(__u32));
__uint(value_size, sizeof(__u32));
} events SEC(".maps");
SEC("tracepoint/syscalls/sys_enter_execve")
int trace_execve(struct trace_event_raw_sys_enter *ctx)
{
struct event evt = {};
evt.pid = bpf_get_current_pid_tgid() >> 32;
evt.uid = bpf_get_current_uid_gid() & 0xFFFFFFFF;
bpf_get_current_comm(&evt.comm, sizeof(evt.comm));
bpf_probe_read_user_str(evt.filename, sizeof(evt.filename),
(const char *)ctx->args[0]);
bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU,
&evt, sizeof(evt));
return 0;
}
char LICENSE[] SEC("license") = "GPL";
Detekcija pokušaja eskalacije privilegija
Ovo je jedan od najkritičnijih sigurnosnih scenarija. Pokušaj eskalacije privilegija (kad neprivilegirani korisnik pokušava dobiti root pristup) treba detektirati u realnom vremenu. eBPF to omogućuje praćenjem promjena UID/GID vrijednosti:
// detect_privesc.bpf.c
#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
#include <linux/sched.h>
struct privesc_event {
__u32 pid;
__u32 old_uid;
__u32 new_uid;
char comm[16];
};
struct {
__uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
__uint(key_size, sizeof(__u32));
__uint(value_size, sizeof(__u32));
} alerts SEC(".maps");
SEC("lsm/cred_prepare")
int BPF_PROG(detect_privilege_escalation,
struct cred *new, const struct cred *old, gfp_t gfp)
{
__u32 old_uid = BPF_CORE_READ(old, uid.val);
__u32 new_uid = BPF_CORE_READ(new, uid.val);
// Detekcija promjene iz neprivilegiranog u privilegirani UID
if (old_uid != 0 && new_uid == 0) {
struct privesc_event evt = {};
evt.pid = bpf_get_current_pid_tgid() >> 32;
evt.old_uid = old_uid;
evt.new_uid = new_uid;
bpf_get_current_comm(&evt.comm, sizeof(evt.comm));
bpf_printk("UPOZORENJE: Eskalacija privilegija! PID=%d, %s: UID %d -> 0
",
evt.pid, evt.comm, old_uid);
bpf_perf_event_output(ctx, &alerts, BPF_F_CURRENT_CPU,
&evt, sizeof(evt));
}
return 0; // Dozvoliti, ali zabilježiti
}
char LICENSE[] SEC("license") = "GPL";
Brza analiza s bpftrace
bpftrace je skriptni jezik visoke razine za eBPF koji omogućuje brzu ad-hoc sigurnosnu analizu. Ako vam treba nešto brzo provjeriti bez pisanja punog C programa, ovo je pravi alat:
# Praćenje svih procesa koji pristupaju /etc/passwd
sudo bpftrace -e 'tracepoint:syscalls:sys_enter_openat
/str(args->filename) == "/etc/passwd"/
{ printf("PID %d (%s) pristupa /etc/passwd
", pid, comm); }'
# Praćenje svih mrežnih konekcija
sudo bpftrace -e 'kprobe:tcp_connect
{ printf("PID %d (%s) uspostavlja TCP vezu
", pid, comm); }'
# Detekcija učitavanja jezgrenih modula
sudo bpftrace -e 'kprobe:load_module
{ printf("UPOZORENJE: Učitavanje modula od PID %d (%s), UID %d
",
pid, comm, uid); }'
# Nadzor brisanja datoteka
sudo bpftrace -e 'tracepoint:syscalls:sys_enter_unlinkat
{ printf("PID %d (%s) briše: %s
", pid, comm, str(args->pathname)); }'
Tetragon - eBPF alat za sigurnosnu opservabilnost
Cilium Tetragon je open-source alat za sigurnosnu opservabilnost i primjenu sigurnosnih politika u stvarnom vremenu. Razvijen je pod okriljem CNCF-a i koristi eBPF za duboko praćenje jezgrenih događaja s — pazite sad — manje od 1% opterećenja procesora.
Ključne mogućnosti Tetragona
- Praćenje procesa — kompletna vidljivost izvršavanja procesa, uključujući stablo procesa
- Nadzor mrežne aktivnosti — praćenje mrežnih veza s kontekstualizacijom
- Praćenje pristupa datotekama — nadzor čitanja, pisanja i brisanja osjetljivih datoteka
- Primjena politika u stvarnom vremenu — blokiranje sumnjivih operacija izravno u jezgri
- Kubernetes integracija — obogaćivanje događaja metapodacima o podovima, imenskim prostorima i kontejnerima
Instalacija Tetragona
# Instalacija putem Helm charta na Kubernetes klaster
helm repo add cilium https://helm.cilium.io
helm repo update
helm install tetragon cilium/tetragon -n kube-system
# Instalacija Tetragon CLI alata
GOOS=$(go env GOOS)
GOARCH=$(go env GOARCH)
curl -L --remote-name-all \
https://github.com/cilium/tetragon/releases/latest/download/tetra-${GOOS}-${GOARCH}.tar.gz
sudo tar -C /usr/local/bin -xzvf tetra-${GOOS}-${GOARCH}.tar.gz
sudo chmod +x /usr/local/bin/tetra
# Za samostalnu instalaciju izvan Kubernetesa
sudo apt install -y tetragon
TracingPolicy - definiranje sigurnosnih politika
Tetragonova najmoćnija značajka su TracingPolicy objekti — Kubernetes CRD-ovi koji definiraju što pratiti i kako reagirati. Evo primjera politike za nadzor pristupa osjetljivim datotekama:
# file-monitoring-policy.yaml
apiVersion: cilium.io/v1alpha1
kind: TracingPolicy
metadata:
name: "monitor-sensitive-files"
spec:
kprobes:
- call: "security_file_open"
syscall: false
args:
- index: 0
type: "file"
selectors:
- matchArgs:
- index: 0
operator: "Prefix"
values:
- "/etc/shadow"
- "/etc/passwd"
- "/etc/sudoers"
- "/root/.ssh/"
matchActions:
- action: Sigkill # Ubij proces koji pokušava pristupiti
- action: Post # Pošalji događaj u korisnički prostor
# Primjena politike na Kubernetes klaster
kubectl apply -f file-monitoring-policy.yaml
# Praćenje događaja u stvarnom vremenu
kubectl logs -n kube-system ds/tetragon -c export-stdout -f | \
tetra getevents -o compact
Primjer: detekcija i blokiranje kriptominera
Kriptomineri su postali prava napast u kontejnerskim okruženjima. Evo kako ih automatski detektirati i blokirati:
# block-crypto-miners.yaml
apiVersion: cilium.io/v1alpha1
kind: TracingPolicy
metadata:
name: "block-crypto-miners"
spec:
kprobes:
- call: "tcp_connect"
syscall: false
args:
- index: 0
type: "sock"
selectors:
- matchArgs:
- index: 0
operator: "DPort"
values:
- "3333" # Stratum mining protokol
- "4444"
- "8333" # Bitcoin
- "9999"
matchActions:
- action: Sigkill
rateLimit: "1m" # Ograničenje obavijesti
Primjer: praćenje izvršavanja procesa
# Jednostavan nadzor izvršavanja procesa
kubectl logs -n kube-system ds/tetragon -c export-stdout -f | \
tetra getevents --process-pid 1234
# Filtriranje prema imenskom prostoru u Kubernetesu
kubectl logs -n kube-system ds/tetragon -c export-stdout -f | \
tetra getevents -o compact --namespace production
Ono po čemu se Tetragon stvarno ističe jest sposobnost izvršavanja sigurnosnih akcija sinkrono unutar jezgre. To znači da se zlonamjerna operacija može blokirati prije nego što proizvede ikakav učinak — za razliku od tradicionalnih sustava koji reagiraju asinkrono, kad je šteta već napravljena.
Falco i eBPF - detekcija anomalija u stvarnom vremenu
Falco je graduirani CNCF projekt koji pruža sigurnosnu zaštitu u stvarnom vremenu za kontejnere, hostove, Kubernetes i oblačna okruženja. Koristi eBPF sonde za prikupljanje jezgrenih događaja s minimalnim opterećenjem (obično manje od 5% po čvoru) i primjenjuje korisnički definirana pravila za detekciju anomalija.
Kako Falco koristi eBPF
Falco se priključuje na jezgru koristeći eBPF sonde (umjesto starijeg pristupa s jezgrenim modulom) te prikuplja događaje poput sustavskih poziva, mrežne aktivnosti i pristupa datotekama. Prikupljene podatke zatim obogaćuje Kubernetes metapodacima — naziv poda, imenski prostor, slika kontejnera — što dramatično olakšava kontekstualizaciju upozorenja.
Instalacija Falca s eBPF podrškom
# Dodavanje Falco repozitorija
helm repo add falcosecurity https://falcosecurity.github.io/charts
helm repo update
# Instalacija s eBPF driverom
helm install falco falcosecurity/falco \
--namespace falco --create-namespace \
--set driver.kind=ebpf \
--set falcosidekick.enabled=true \
--set falcosidekick.webui.enabled=true
# Za samostalnu instalaciju na hostu
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 update && sudo apt install -y falco
Falco pravila za sigurnosnu detekciju
Falco pravila pišu se u YAML formatu. Moram priznati, sintaksa je prilično intuitivna čak i za početnike. Evo nekoliko pravila koja pokrivaju najčešće sigurnosne scenarije:
# custom_rules.yaml
# Pravilo: Detekcija pokretanja ljuske u kontejneru
- rule: Shell pokrenut u kontejneru
desc: Detektirano pokretanje ljuske unutar kontejnera
condition: >
spawned_process and container and
proc.name in (bash, sh, zsh, dash, ksh) and
not proc.pname in (cron, crond, supervisord)
output: >
Ljuska pokrenuta u kontejneru
(korisnik=%user.name kontejner=%container.name
slika=%container.image.repository
naredba=%proc.cmdline pid=%proc.pid
imenski_prostor=%k8s.ns.name pod=%k8s.pod.name)
priority: WARNING
tags: [container, shell, mitre_execution]
# Pravilo: Detekcija pisanja u /etc direktorij
- rule: Pisanje u sistemski direktorij
desc: Detektirano pisanje u osjetljive sistemske direktorije
condition: >
open_write and container and
fd.directory in (/etc, /usr/bin, /usr/sbin, /bin, /sbin) and
not proc.name in (apt, dpkg, yum, rpm, pip)
output: >
Pisanje u sistemski direktorij iz kontejnera
(datoteka=%fd.name proces=%proc.name
kontejner=%container.name slika=%container.image.repository
imenski_prostor=%k8s.ns.name)
priority: ERROR
tags: [container, filesystem, mitre_persistence]
# Pravilo: Detekcija mrežnog alata u kontejneru
- rule: Mrežni alat u kontejneru
desc: Detektirano korištenje mrežnog alata unutar kontejnera
condition: >
spawned_process and container and
proc.name in (nc, ncat, nmap, tcpdump, wireshark, tshark,
netcat, socat, curl, wget) and
not user.name = "root"
output: >
Sumnjivi mrežni alat pokrenut u kontejneru
(alat=%proc.name korisnik=%user.name
kontejner=%container.name naredba=%proc.cmdline)
priority: NOTICE
tags: [container, network, mitre_discovery]
Praćenje Falco upozorenja
# Pregled Falco upozorenja u stvarnom vremenu
sudo falco -r /etc/falco/custom_rules.yaml
# Pregled logova na Kubernetesu
kubectl logs -n falco -l app.kubernetes.io/name=falco -f
# Integracija s Falcosidekick za prosljeđivanje upozorenja
# Podržava: Slack, PagerDuty, Elasticsearch, Kafka, webhook i 50+ integracija
Hornet LSM - provjera potpisa eBPF programa
Hornet je Linux Security Module koji je razvio Microsoft, a rješava jedno kritično pitanje: kako osigurati da se samo odobreni, verificirani eBPF programi mogu učitati u jezgru?
Razmislite o tome — bez mehanizma poput Horneta, napadač s CAP_BPF privilegijom mogao bi učitati proizvoljni eBPF program u jezgru i zaobići sve postojeće sigurnosne kontrole. To je ozbiljan problem.
Kako Hornet funkcionira
Hornet implementira mehanizam provjere potpisa eBPF programa koji se izvršava u jezgrenom prostoru. Evo ključnih aspekata:
- PKCS#7 potpisi — svaki eBPF program potpisuje se kriptografskim potpisom koji se dodaje na kraj izvršne datoteke
- Verifikacija pri učitavanju — potpis se provjerava putem
bpf_prog_loadsustavskog poziva, prije nego što program uopće dospije do verifikatora - Hash mapa — osim samih instrukcija, potpisuju se i početne vrijednosti eBPF mapa
- Zamrzavanje mapa (Map freezing) — mape se zamrzavaju prije provjere potpisa, čime se sprječavaju TOCTOU (Time-of-Check-Time-of-Use) napadi
Potpisivanje eBPF programa s Hornetom
# Generiranje ključeva za potpisivanje
openssl req -x509 -newkey rsa:4096 -keyout ebpf-signing-key.pem \
-out ebpf-signing-cert.pem -days 365 -nodes \
-subj "/CN=eBPF Signing Key/O=MojaOrganizacija"
# Korištenje sign-ebpf alata za potpisivanje programa
sign-ebpf --key ebpf-signing-key.pem \
--cert ebpf-signing-cert.pem \
--input my_security_program \
--output my_security_program.signed
# Provjera potpisa
sign-ebpf --verify \
--cert ebpf-signing-cert.pem \
--input my_security_program.signed
Konfiguracija jezgre za Hornet
# Potrebne konfiguracijske opcije jezgre
CONFIG_SECURITY_HORNET=y
CONFIG_BPF_LSM=y
# Dodavanje Horneta u LSM listu
# /etc/default/grub:
GRUB_CMDLINE_LINUX="lsm=lockdown,capability,yama,apparmor,bpf,hornet"
# Dodavanje certifikata za potpisivanje u jezgreni keyring
sudo keyctl padd asymmetric "eBPF signing key" %:.ebpf_signing \
< ebpf-signing-cert.der
Hornet je posebno značajan za produkcijska okruženja. Iako je u trenutku pisanja ovog vodiča još u fazi razvoja i rasprave s Linux zajednicom, predstavlja važan korak prema sigurnijem eBPF ekosustavu.
Živo krpanje ranjivosti s eBPF-om
Ovo je osobno jedna od mojih omiljenih primjena eBPF-a. Zamislite — možete zakrpati sigurnosnu ranjivost jezgre bez restarta sustava. Cloudflare je pionir ovog pristupa i demonstrirao je kako eBPF može zaštititi od poznatih ranjivosti dok se čeka službeno ažuriranje.
Problem: ranjivosti korisničkih imenskih prostora
Korisnički imenski prostori (user namespaces) u Linuxu povećavaju napadačku površinu jezgre jer omogućuju neprivilegiranim korisnicima pristup sučeljima koja su inače rezervirana za root. Cloudflare je koristio eBPF LSM za blokiranje neovlaštenog stvaranja korisničkih imenskih prostora.
Cloudflareov pristup živom krpanju
// block_userns.bpf.c - Blokiranje stvaranja korisničkih imenskih prostora
#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
#include <linux/errno.h>
// Mapa s dozvolama - PID-ovi kojima je dopušteno stvaranje
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, 1024);
__type(key, __u32);
__type(value, __u8);
} allowed_pids SEC(".maps");
SEC("lsm/cred_prepare")
int BPF_PROG(block_userns_create,
struct cred *new, const struct cred *old, gfp_t gfp)
{
__u32 pid = bpf_get_current_pid_tgid() >> 32;
__u32 uid = bpf_get_current_uid_gid() & 0xFFFFFFFF;
// Dozvoli root korisniku
if (uid == 0)
return 0;
// Provjeri je li PID na listi dozvoljenih
__u8 *allowed = bpf_map_lookup_elem(&allowed_pids, &pid);
if (allowed)
return 0;
// Blokiraj neprivilegiranim korisnicima
bpf_printk("Blokirano stvaranje user namespace: PID=%d UID=%d
",
pid, uid);
return -EPERM;
}
char LICENSE[] SEC("license") = "GPL";
CO-RE pristup za prenosivost
Cloudflare koristi CO-RE (Compile Once - Run Everywhere) pristup koji omogućuje pisanje eBPF programa jednom i pokretanje na različitim verzijama jezgre. CO-RE automatski obavlja potrebne relokacije prema BTF informacijama dostupne jezgre — što je u praksi ogromna ušteda vremena:
# Prevođenje s CO-RE podrškom
clang -O2 -target bpf -g \
-D__TARGET_ARCH_x86 \
-I/usr/include/bpf \
-c block_userns.bpf.c -o block_userns.bpf.o
# Generiranje kostura za korisnički prostor
bpftool gen skeleton block_userns.bpf.o > block_userns.skel.h
# Učitavanje programa
sudo ./block_userns_loader
Prednosti nad tradicionalnim krpanjem
- Bez ponovnog pokretanja — zakrpa se primjenjuje trenutno, bez prekida rada servisa
- Brza implementacija — eBPF zakrpa može biti razvijena i primijenjena u satima, dok službene zakrpe jezgre ponekad trebaju tjedne
- Reverzibilnost — zakrpa se može ukloniti jednako brzo kao što je primijenjena
- Granularnost — moguće je primijeniti zakrpu samo na specifične scenarije, bez utjecaja na ostatak sustava
- Prenosivost — CO-RE program radi na svim jezgrama s BTF podrškom (5.x+)
Sigurnosni rizici eBPF-a - dvosjekli mač
Iako je eBPF izuzetno moćan obrambeni alat, moramo biti iskreni — ista ta moć čini ga potencijalno opasnim vektorom napada. Razumijevanje ovih rizika nije opcija, već nužnost za svaku organizaciju koja implementira eBPF sigurnosne sustave.
eBPF kao vektor napada
Podaci iz 2025. godine jasno pokazuju da eBPF malware nije teorijski problem. FortiGuard Labs je identificirao 151 novi uzorak BPFDoor malvera i tri varijante Symbiote zlonamjernog softvera. Ključni vektori napada uključuju:
- BPF filteri na sirovim utičnicama — zlonamjerni bajtkod priključen putem
SO_ATTACH_FILTERfiltrira mrežne pakete na razini jezgre, aktivirajući backdoor na primljeni "magični" paket - Skrivanje procesa i datoteka — rootkiti koriste eBPF programe za presretanje
getdentssustavskog poziva, čime skrivaju svoje datoteke i procese - Samoskrivanje eBPF programa — napredniji rootkiti presreću
sys_bpfpoziv kako bi sakrili vlastite eBPF programe od alata poputbpftool - Mrežni backdoor — eBPF program na XDP ili TC razini čeka posebno oblikovani TCP paket koji aktivira udaljenu ljusku
Primjer: LinkPro rootkit (2025.)
LinkPro je eBPF rootkit otkriven 2025. koji koristi eBPF za skrivanje i aktivaciju putem magičnih TCP paketa. Ovaj primjer pokazuje koliko su moderne eBPF prijetnje sofisticirane — operiraju unutar pouzdanog jezgrenog prostora, ispod dosega većine revizijskih okvira i sigurnosnih agenata.
Ključni izazov: nevidljivost za tradicionalne alate
Antivirusna rješenja opće namjene jednostavno ne mogu detektirati eBPF backdoore. Zašto? Jer eBPF programi ne postoje izravno u datotečnom sustavu — učitavaju se u jezgrin BPF podsustav i izvršavaju se samo pri specifičnim događajima. Klasičan file scan tu nema što pronaći.
Mitigacijske strategije
Obrana od zlonamjernog korištenja eBPF-a zahtijeva slojeviti pristup. Evo konkretnih koraka:
- Ograničavanje pristupa BPF sustavskom pozivu
# Ograničavanje BPF na privilegirane korisnike sudo sysctl kernel.unprivileged_bpf_disabled=1 # Trajno postavljanje echo "kernel.unprivileged_bpf_disabled=1" | \ sudo tee /etc/sysctl.d/99-ebpf-hardening.conf - Nadzor eBPF aktivnosti
# Redovita inspekcija učitanih eBPF programa sudo bpftool prog list # Posebna pozornost na sumnjive tipove # (kprobe, tracepoint na getdents, XDP programi) sudo bpftool prog list | grep -E "kprobe|tracepoint|xdp" # Provjera eBPF mapa koje koriste sumnjivi programi sudo bpftool map list - Korištenje specijaliziranih alata za detekciju
# Instalacija Tracee-a za nadzor eBPF aktivnosti docker run --name tracee -it --rm \ --pid=host --cgroupns=host --privileged \ -v /etc/os-release:/etc/os-release-host:ro \ -v /boot/config-$(uname -r):/boot/config-$(uname -r):ro \ aquasec/tracee:latest - Implementacija Hornet LSM-a za kriptografsku provjeru potpisa eBPF programa
- Sustav otkrivanja integriteta jezgre — alati poput LKRG (Linux Kernel Runtime Guard) koji detektiraju neovlaštene promjene jezgrenih struktura
Praktični vodič za implementaciju eBPF sigurnosne platforme
Sad kad razumijemo teoriju, prijeđimo na konkretnu implementaciju. Proći ćemo korak po korak kroz postavljanje eBPF sigurnosne platforme, od provjere preduvjeta do pisanja prve sigurnosne politike.
Korak 1: Provjera podrške jezgre
# Provjera verzije jezgre (potrebna >= 5.7 za BPF LSM)
uname -r
# Provjera BPF konfiguracije jezgre
cat /boot/config-$(uname -r) | grep CONFIG_BPF
# Tražimo:
# CONFIG_BPF=y
# CONFIG_BPF_SYSCALL=y
# CONFIG_BPF_JIT=y
# CONFIG_BPF_LSM=y
# Provjera BTF podrške (potrebno za CO-RE)
cat /boot/config-$(uname -r) | grep BTF
# Tražimo:
# CONFIG_DEBUG_INFO_BTF=y
# Provjera dostupnosti BTF datoteka
ls -la /sys/kernel/btf/vmlinux
# Provjera aktivnih LSM modula
cat /sys/kernel/security/lsm
Korak 2: Instalacija potrebnih alata
# Na Ubuntu/Debian sustavima
sudo apt update
sudo apt install -y \
build-essential \
clang \
llvm \
libbpf-dev \
linux-headers-$(uname -r) \
linux-tools-$(uname -r) \
bpftool \
bpftrace
# Na Fedora/RHEL sustavima
sudo dnf install -y \
clang \
llvm \
libbpf-devel \
kernel-headers \
bpftool \
bpftrace
# Provjera instalacije
bpftool version
bpftrace --version
clang --version
Korak 3: Omogućavanje BPF LSM-a
# Provjera trenutne LSM konfiguracije
cat /sys/kernel/security/lsm
# Primjer: lockdown,capability,yama,apparmor
# Dodavanje BPF u LSM listu
sudo sed -i 's/^GRUB_CMDLINE_LINUX="\(.*\)"/GRUB_CMDLINE_LINUX="\1 lsm=lockdown,capability,yama,apparmor,bpf"/' \
/etc/default/grub
# Ažuriranje GRUB-a
sudo update-grub # Debian/Ubuntu
# ili
sudo grub2-mkconfig -o /boot/grub2/grub.cfg # Fedora/RHEL
# Ponovno pokretanje sustava
sudo reboot
# Nakon ponovnog pokretanja, provjera
cat /sys/kernel/security/lsm
# Sada bi trebalo sadržavati: ...apparmor,bpf
Korak 4: Pisanje prve sigurnosne politike
Vrijeme je za pravu stvar. Kreirajmo potpunu sigurnosnu politiku koja blokira pokretanje specifičnih opasnih programa:
// block_dangerous_exec.bpf.c
// eBPF LSM program za blokiranje pokretanja opasnih programa
#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
#include <linux/errno.h>
// Mapa za pohranu hasheva blokiranih programa
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, 256);
__type(key, char[64]);
__type(value, __u8);
} blocked_binaries SEC(".maps");
SEC("lsm/bprm_check_security")
int BPF_PROG(block_exec, struct linux_binprm *bprm)
{
char filename[64] = {};
const char *name;
// Čitanje naziva datoteke iz bprm strukture
name = BPF_CORE_READ(bprm, filename);
bpf_probe_read_kernel_str(filename, sizeof(filename), name);
// Provjera je li program na listi blokiranih
__u8 *blocked = bpf_map_lookup_elem(&blocked_binaries, filename);
if (blocked) {
__u32 pid = bpf_get_current_pid_tgid() >> 32;
__u32 uid = bpf_get_current_uid_gid() & 0xFFFFFFFF;
bpf_printk("BLOKIRANO: %s od PID=%d UID=%d
",
filename, pid, uid);
return -EPERM;
}
return 0;
}
char LICENSE[] SEC("license") = "GPL";
Korak 5: Prevođenje i učitavanje programa
# Prevođenje eBPF programa
clang -O2 -target bpf -g \
-D__TARGET_ARCH_x86 \
-I/usr/include/bpf \
-c block_dangerous_exec.bpf.c \
-o block_dangerous_exec.bpf.o
# Generiranje kostura
bpftool gen skeleton block_dangerous_exec.bpf.o \
> block_dangerous_exec.skel.h
# Provjera ispravnosti objektne datoteke
bpftool prog load block_dangerous_exec.bpf.o /sys/fs/bpf/block_exec \
type lsm attach_type mac
# Provjera da je program učitan
sudo bpftool prog list | grep block_exec
# Pregled jezgrenog loga za praćenje blokiranih pokušaja
sudo dmesg -w | grep BLOKIRANO
Korak 6: Postavljanje sustava za nadzor
# Kreiranje systemd servisa za automatsko pokretanje
sudo tee /etc/systemd/system/ebpf-security.service << 'EOF'
[Unit]
Description=eBPF Security Policy Enforcement
After=network.target
[Service]
Type=simple
ExecStart=/usr/local/bin/ebpf-security-loader
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
# Aktivacija servisa
sudo systemctl daemon-reload
sudo systemctl enable --now ebpf-security.service
# Provjera statusa
sudo systemctl status ebpf-security.service
Korak 7: Integracija s postojećim sigurnosnim sustavima
# Prosljeđivanje eBPF upozorenja u syslog
# Dodati u korisnički program za učitavanje:
# openlog("ebpf-security", LOG_PID, LOG_AUTH);
# syslog(LOG_ALERT, "Blokiran pokušaj: %s", event_info);
# Integracija s auditd sustavom
sudo auditctl -a always,exit -F arch=b64 -S bpf -k ebpf-activity
# Pregled revizijskih zapisa
sudo ausearch -k ebpf-activity
# Prosljeđivanje u SIEM putem rsyslog-a
# /etc/rsyslog.d/50-ebpf-security.conf
# :programname, isequal, "ebpf-security" @@siem-server:514
Korak 8: Ojačavanje sustava
# Onemogućavanje neprivilegiranog pristupa BPF-u
sudo sysctl -w kernel.unprivileged_bpf_disabled=1
# Trajno postavljanje
echo "kernel.unprivileged_bpf_disabled=1" | \
sudo tee -a /etc/sysctl.d/99-ebpf-hardening.conf
# Omogućavanje JIT hardeninga
sudo sysctl -w net.core.bpf_jit_harden=2
echo "net.core.bpf_jit_harden=2" | \
sudo tee -a /etc/sysctl.d/99-ebpf-hardening.conf
# Primjena sysctl postavki
sudo sysctl --system
# Provjera sigurnosnog stanja
echo "=== eBPF Sigurnosno stanje ==="
echo "Neprivilegirani BPF: $(sysctl -n kernel.unprivileged_bpf_disabled)"
echo "JIT Hardening: $(sysctl -n net.core.bpf_jit_harden)"
echo "Aktivni LSM: $(cat /sys/kernel/security/lsm)"
echo "Učitani BPF programi: $(sudo bpftool prog list | wc -l)"
Zaključak i budućnost eBPF sigurnosti
eBPF je nedvojbeno transformirao sigurnosni krajolik Linux sustava. Od jednostavnog filtra mrežnih paketa iz 1992. godine, prerastao je u potpunu sigurnosnu platformu koja omogućuje nadzor, detekciju i primjenu politika s dosad neviđenom razinom granularnosti — i to uz minimalan utjecaj na performanse.
Trenutno stanje ekosustava
Do 2026., eBPF je postao temelj moderne infrastrukture za sigurnost, mrežu i opservabilnost. Tetragon pruža sinkronu primjenu sigurnosnih politika unutar jezgre, Falco omogućuje sofisticiranu detekciju anomalija obogaćenu kontejnerskim i Kubernetes metapodacima, a Hornet LSM obećava kriptografsku provjeru integriteta eBPF programa. Cloudflareov pristup živom krpanju pokazuje kako eBPF može dramatično skratiti vremenski prozor izloženosti poznatim ranjivostima.
Ključni trendovi za budućnost
- Kriptografska provjera eBPF programa — projekti poput Horneta postat će standard za produkcijska okruženja
- Autonomna sigurnost u Kubernetesu — eBPF pokreće pomak prema samoobrambenim klasterima koji automatski reagiraju na prijetnje
- Napredna detekcija eBPF prijetnji — rast eBPF rootkita potaknut će razvoj specijaliziranih alata za nadzor samog eBPF podsustava
- Proširenje na Windows — Microsoftov projekt eBPF for Windows donosi istu paradigmu na Windows platformu
Razmatranja kvantne sigurnosti
S napretkom kvantnog računarstva, sigurnosna zajednica mora razmotriti budućnost kriptografskih mehanizama u eBPF ekosustavu. Trenutni PKCS#7 potpisi (korišteni u alatima poput Horneta) temelje se na RSA i ECDSA algoritmima koji su potencijalno ranjivi na kvantne napade. Kao proaktivnu mjeru, vrijedi razmotriti integraciju kvantno otpornih algoritama u sigurnosne tokove. Primjerice, za SSH komunikaciju prema sustavima koji upravljaju eBPF infrastrukturom:
# /etc/ssh/sshd_config - kvantno otporna razmjena ključeva
KexAlgorithms [email protected],curve25519-sha256
# Provjera podržanih algoritama
ssh -Q kex | grep sntrup
Budućnost eBPF sigurnosti izgleda svijetlo, ali zahtijeva stalan oprez. Ista tehnologija koja pruža neusporedivu vidljivost i kontrolu može biti zloupotrijebljena ako se ne primijene odgovarajuće mjere zaštite. Slojeviti pristup — ojačavanje jezgre, ograničavanje pristupa BPF sustavskom pozivu, nadzor eBPF aktivnosti i kriptografska provjera programa — ključan je za sigurno iskorištavanje punog potencijala eBPF-a.
Ako ste tek na početku, slijedite korake iz ovog vodiča i pratite brzi razvoj eBPF ekosustava. Svaka nova verzija Linux jezgre donosi nove mogućnosti — a s njima i nove razloge da eBPF postane srž vaše sigurnosne strategije.