eBPF kao moderna sigurnosna platforma za Linux: Vodič za nadzor, detekciju prijetnji i primjenu politika

Naučite kako koristiti eBPF za sigurnosni nadzor Linux sustava. Praktični vodič s primjerima za Tetragon, Falco, BPF LSM, Hornet i živo krpanje ranjivosti — od arhitekture do implementacije.

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_load sustavskog 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_FILTER filtrira mrežne pakete na razini jezgre, aktivirajući backdoor na primljeni "magični" paket
  • Skrivanje procesa i datoteka — rootkiti koriste eBPF programe za presretanje getdents sustavskog poziva, čime skrivaju svoje datoteke i procese
  • Samoskrivanje eBPF programa — napredniji rootkiti presreću sys_bpf poziv kako bi sakrili vlastite eBPF programe od alata poput bpftool
  • 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:

  1. 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
  2. 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
  3. 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
  4. Implementacija Hornet LSM-a za kriptografsku provjeru potpisa eBPF programa
  5. 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.

O Autoru Editorial Team

Our team of expert writers and editors.