
Strumento di sicurezza basato su eBPF per bloccare e monitorare macchine Linux. Limita le funzionalità del kernel, blocca l'esecuzione senza file, protegge la memoria e rinforza contenitori e dispositivi IoT tramite profili dichiarativi.

bpflock - sicurezza basata su eBPF per bloccare e controllare le macchine Linux.
Nota: bpflock è attualmente in fase sperimentale, potrebbe rompersi, le opzioni e la semantica di sicurezza potrebbero cambiare, alcuni programmi BPF saranno aggiornati per utilizzare la libreria Cilium ebpf.
bpflock utilizza eBPF per rafforzare la sicurezza di Linux. Limitando l'accesso a una vasta gamma di funzionalità di Linux, bpflock è in grado di ridurre la superficie d'attacco e bloccare alcune tecniche di attacco ben note.
Solo i programmi come i gestori di container, systemd e altri container/programmi che vengono eseguiti negli spazi dei nomi pid e di rete dell'host hanno accesso completo a
caratteristiche di Linux, mentre i container e le applicazioni che vengono eseguiti nel proprio spazio dei nomi saranno limitati.
Se i programmi bpf di bpflock vengono eseguiti con il profilo restricted, allora tutti i programmi/container, inclusi quelli privilegiati, avranno accesso negato.
bpflock protegge le macchine Linux sfruttando molteplici funzionalità di sicurezza, inclusi Linux Security Modules + BPF.
Note sull'architettura e sulla progettazione della sicurezza:
bpflock offre molteplici protezioni di sicurezza che possono essere classificate come:
Tracciamento di sistema e applicazioni
Protezioni del filesystem
Protezioni di rete
bpflock mantiene la semantica di sicurezza semplice. Supporta tre profili globali per coprire ampiamente lo spettro di sicurezza e limitare l'accesso a specifiche funzionalità di Linux.
profile: questo è il profilo globale che può essere applicato per programma bpf, accetta uno dei seguenti valori:
allow|none|privileged : sono equivalenti, definiscono il profilo meno sicuro. In questo profilo l'accesso viene registrato e consentito per tutti i processi. Utile per registrare eventi di sicurezza.baseline : profilo restrittivo in cui l'accesso è negato per tutti i processi, tranne le applicazioni e i container privilegiati che vengono eseguiti negli spazi dei nomi dell'host, o i profili consentiti per cgroup nella mappa bpf bpflock_cgroupmap.restricted : profilo fortemente restrittivo in cui l'accesso è negato per tutti i processi.Operazioni/comandi Allowed o blocked:
Sotto i profili allow|privileged o baseline, è possibile specificare un elenco di comandi consentiti o bloccati che verranno applicati.
--protection-allow : elenco separato da virgole di operazioni consentite. Valido sotto il profilo baseline, utile per applicazioni troppo specifiche che eseguono operazioni privilegiate. Ridurrà l'uso del profilo , quindi invece di usare il profilo , possiamo specificare e aggiungere un insieme di comandi consentiti per offrire una definizione caso per caso per tali applicazioni.Per esempi di sicurezza bpf consulta esempi di configurazione bpflock
bpflock richiede quanto segue:
Versione del kernel Linux >= 5.13 con la seguente configurazione:
CONFIG_BPF_SYSCALL=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO_BTF=y
CONFIG_KPROBES=y
CONFIG_LSM="...,bpf"
CONFIG_BPF_LSM=y
Ovviamente un kernel con BTF abilitato.
Se il tuo kernel è stato compilato con CONFIG_BPF_LSM=y, controlla /boot/config-* per confermare, ma se durante l'esecuzione di bpflock fallisce con:
must have a kernel with 'CONFIG_BPF_LSM=y' 'CONFIG_LSM=\"...,bpf\"'"
Quindi per abilitare BPF LSM come esempio su Ubuntu:
GRUB_CMDLINE_LINUX e salva.
"lsm=lockdown,capability,yama,apparmor,bpf"
GRUB_CMDLINE_LINUX="lsm=lockdown,capability,yama,apparmor,bpf"
sudo update-grub2
Per eseguire utilizzando il profilo predefinito allow o privileged (il profilo meno sicuro):
docker run --name bpflock -it --rm --cgroupns=host \
--pid=host --privileged \
-v /sys/kernel/:/sys/kernel/ \
-v /sys/fs/bpf:/sys/fs/bpf linuxlock/bpflock
Per registrare e limitare l'esecuzione binaria senza file esegui con:
docker run --name bpflock -it --rm --cgroupns=host --pid=host --privileged \
-e "BPFLOCK_FILELESSLOCK_PROFILE=restricted" \
-v /sys/kernel/:/sys/kernel/ \
-v /sys/fs/bpf:/sys/fs/bpf linuxlock/bpflock
Quando viene eseguito con il profilo restricted, i log del container mostreranno:
time="2022-02-04T14:54:33Z" level=info msg="event=syscall_execve tgid=1833 pid=1833 ppid=1671 uid=1000 cgroupid=8821 comm=loader pcomm=bash filename=./loader retval=0" bpfprog=execsnoop subsys=bpf
time="2022-02-04T14:54:33Z" level=info msg="event=lsm_bprm_creds_from_file tgid=1833 pid=1833 ppid=1671 uid=1000 cgroupid=8821 comm=loader pcomm=bash filename=memfd:memfd-test retval=-1 reason=denied (restricted)" bpfprog=filelesslock subsys=bpf
time="2022-02-04T14:54:33Z" level=info msg="event=syscall_execve tgid=1833 pid=1833 ppid=0 uid=1000 cgroupid=8821 comm= pcomm= filename=/proc/self/fd/3 retval=-1" bpfprog=execsnoop subsys=bpf
Eseguire con il profilo restricted potrebbe rompere le cose, ecco perché il profilo predefinito è allow.
Per applicare la Protezione dei moduli del kernel
esegui con la variabile d'ambiente BPFLOCK_KMODLOCK_PROFILE=baseline o BPFLOCK_KMODLOCK_PROFILE=restricted:
docker run --name bpflock -it --rm --cgroupns=host --pid=host --privileged \
-e "BPFLOCK_KMODLOCK_PROFILE=restricted" \
-v /sys/kernel/:/sys/kernel/ \
-v /sys/fs/bpf:/sys/fs/bpf linuxlock/bpflock
Esempio:
$ sudo unshare -p -n -f
# modprobe xfs
modprobe: ERROR: could not insert 'xfs': Operation not permitted
time="2022-02-07T06:50:25+01:00" level=info msg="event=syscall_execve tgid=52323 pid=52323 ppid=52288 uid=0 cgroupid=7014 comm=modprobe pcomm=bash filename=/usr/sbin/modprobe retval=0" bpfprog=execsnoop subsys=bpf
time="2022-02-07T06:50:25+01:00" level=info msg="event=lsm_kernel_read_file operation=loading module tgid=52323 pid=52323 ppid=52288 uid=0 cgroupid=7014 comm=modprobe pcomm=bash filename=xfs.ko retval=-1 reason=denied (restricted)" bpfprog=kmodlock subsys=bpf
Per applicare il Blocco dell'immagine del kernel esegui con la variabile d'ambiente BPFLOCK_KIMGLOCK_PROFILE=baseline:
docker run --name bpflock -it --rm --cgroupns=host --pid=host --privileged \
-e "BPFLOCK_KIMGLOCK_PROFILE=baseline" \
-v /sys/kernel/:/sys/kernel/ \
-v /sys/fs/bpf:/sys/fs/bpf linuxlock/bpflock
$ sudo unshare -f -p -n bash
# head -c 1 /dev/mem
head: cannot open '/dev/mem' for reading: Operation not permitted
time="2022-02-07T06:57:22+01:00" level=info msg="event=syscall_execve tgid=52428 pid=52428 ppid=52288 uid=0 cgroupid=7014 comm=head pcomm=bash filename=/usr/bin/head retval=0" bpfprog=execsnoop subsys=bpf
time="2022-02-07T06:57:22+01:00" level=info msg="event=lsm_locked_down operation=/dev/mem,kmem,port tgid=52428 pid=52428 ppid=52288 uid=0 cgroupid=7014 comm=head pcomm=bash retval=-1 reason=denied (baseline)" bpfprog=kimglock subsys=bpf
Per applicare la restrizione bpf esegui con la variabile d'ambiente BPFLOCK_BPFRESTRICT_PROFILE=baseline o BPFLOCK_BPFRESTRICT_PROFILE=restricted:
docker run --name bpflock -it --rm --cgroupns=host --pid=host --privileged \
-e "BPFLOCK_BPFRESTRICT_PROFILE=baseline" \
-v /sys/kernel/:/sys/kernel/ \
-v /sys/fs/bpf:/sys/fs/bpf linuxlock/bpflock
Esempio eseguito in spazi dei nomi pid e di rete diversi e utilizzando bpftool:
$ sudo unshare -f -p -n bash
# bpftool prog
Error: can't get next program: Operation not permitted
time="2022-02-04T15:40:56Z" level=info msg="event=lsm_bpf tgid=2378 pid=2378 ppid=2364 uid=0 cgroupid=9458 comm=bpftool pcomm=bash filename= retval=-1 reason=baseline" bpfprog=bpfrestrict subsys=bpf
time="2022-02-04T15:40:56Z" level=info msg="event=lsm_bpf tgid=2378 pid=2378 ppid=2364 uid=0 cgroupid=9458 comm=bpftool pcomm=bash filename= retval=-1 reason=baseline" bpfprog=bpfrestrict subsys=bpf
Eseguendo con il profilo -e "BPFLOCK_BPFRESTRICT_PROFILE=restricted" negherà bpf per tutti:
time="2022-02-04T15:44:13Z" level=info msg="event=syscall_execve tgid=2500 pid=2500 ppid=2499 uid=0 cgroupid=9458 comm=bpftool pcomm=sudo filename=./tools/amd64/bpftool retval=0" bpfprog=execsnoop subsys=bpf
time="2022-02-04T15:44:13Z" level=info msg="event=lsm_bpf tgid=2500 pid=2500 ppid=2499 uid=0 cgroupid=9458 comm=bpftool pcomm=sudo filename= retval=-1 reason=denied (restricted)" bpfprog=bpfrestrict subsys=bpf
time="2022-02-04T15:44:13Z" level=info msg="event=lsm_bpf tgid=2500 pid=2500 ppid=2499 uid=0 cgroupid=9458 comm=bpftool pcomm=sudo filename= retval=-1 reason=denied (restricted)" bpfprog=bpfrestrict subsys=bpf
Passare la configurazione come bind mount può essere ottenuto utilizzando il comando seguente.
Supponendo che bpflock.yaml e le configurazioni dei profili bpf.d si trovino nella directory corrente all'interno della directory bpflock, allora possiamo semplicemente usare:
ls bpflock/
bpf.d bpflock.d bpflock.yaml
docker run --name bpflock -it --rm --cgroupns=host --pid=host --privileged \
-v $(pwd)/bpflock/:/etc/bpflock \
-v /sys/kernel/:/sys/kernel/ \
-v /sys/fs/bpf:/sys/fs/bpf linuxlock/bpflock
È anche possibile passare variabili d'ambiente con file utilizzando --env-file. Tutti i parametri possono essere passati come variabili d'ambiente utilizzando il formato BPFLOCK_$VARIABLE_NAME=VALUE.
Esempio di esecuzione con variabili d'ambiente in un file:
docker run --name bpflock -it --rm --cgroupns=host --pid=host --privileged \
--env-file bpflock.env.list \
-v /sys/kernel/:/sys/kernel/ \
-v /sys/fs/bpf:/sys/fs/bpf linuxlock/bpflock
I file di documentazione sono disponibili qui.
bpflock utilizza docker BuildKit per la build e Golang per eseguire alcuni controlli e test. bpflock viene costruito all'interno di un container Ubuntu che scarica il pacchetto golang standard.
Esegui quanto segue per costruire il container docker bpflock:
git submodule update --init --recursive
make
I programmi Bpf sono costruiti utilizzando libbpf. L'immagine docker utilizzata è Ubuntu.
Se desideri costruire solo i programmi bpf direttamente senza utilizzare docker, allora su Ubuntu:
sudo apt install -y pkg-config bison binutils-dev build-essential \
flex libc6-dev clang-12 libllvm12 llvm-12-dev libclang-12-dev \
zlib1g-dev libelf-dev libfl-dev gcc-multilib zlib1g-dev \
libcap-dev libiberty-dev libbfd-dev
Quindi esegui:
make bpf-programs
In questo caso i programmi generati si troveranno nella directory ./bpf/build/...
bpflock utilizza molte risorse, incluso codice sorgente dai progetti Cilium e bcc.
I componenti dello spazio utente di bpflock sono concessi in licenza secondo l'Apache License, Version 2.0. Il codice BPF, dove indicato, è concesso in licenza secondo la General Public License, Version 2.0.
allow | privilegedprivilegedbaseline--protection-block : elenco separato da virgole di operazioni bloccate. Valido sotto i profili allow|privileged e baseline, consente di limitare l'accesso ad alcune funzionalità senza utilizzare il profilo restricted completo che potrebbe rompere alcune applicazioni specifiche. L'uso dei profili baseline o privileged apre la porta all'accesso alla maggior parte delle funzionalità Linux, ma con l'opzione --protection-block parte di questo accesso può essere bloccata.