
Инструмент безопасности на основе eBPF для блокировки и аудита Linux-машин. Ограничивает возможности ядра, блокирует бесфайловое выполнение, защищает память и укрепляет защиту контейнеров и IoT-устройств с помощью декларативных профилей.

bpflock — безопасность на основе eBPF для блокировки и аудита Linux-машин.
Примечание: bpflock currently находится на экспериментальной стадии, возможны сбои, параметры и семантика безопасности могут измениться, некоторые BPF-программы будут обновлены для использования библиотеки Cilium ebpf.
bpflock использует eBPF для усиления безопасности Linux. Ограничивая доступ к широкому спектру функций Linux, bpflock может уменьшить поверхность атаки и заблокировать некоторые известные методы атак.
Только программы, такие как менеджеры контейнеров, systemd и другие контейнеры/программы, работающие в пространствах имен pid и network хоста, имеют доступ ко всем функциям Linux; контейнеры и приложения, работающие в своих собственных пространствах имен, будут ограничены.
Если BPF-программы bpflock работают в профиле restricted, то всем программам/контейнерам, включая привилегированные, будет отказано в доступе.
bpflock защищает Linux-машины, используя множество функций безопасности, включая Linux Security Modules + BPF.
Заметки по архитектуре и дизайну безопасности:
bpflock предоставляет множество защитных мер, которые можно классифицировать следующим образом:
Трассировка системы и приложений
Защита файловой системы
Сетевая защита
bpflock сохраняет семантику безопасности простой. Он поддерживает три глобальных профиля для широкого охвата спектра безопасности и ограничения доступа к определенным функциям Linux.
profile: это глобальный профиль, который может быть применен к каждой BPF-программе; он принимает одно из следующих значений:
allow|none|privileged: они одинаковы и определяют наименее безопасный профиль. В этом профиле доступ регистрируется и разрешается для всех процессов. Полезно для регистрации событий безопасности.baseline: ограничительный профиль, в котором доступ запрещен для всех процессов, кроме привилегированных приложений и контейнеров, работающих в пространствах имен хоста, или профилей, разрешенных для каждой cgroup в BPF-карте bpflock_cgroupmap.restricted: строго ограничительный профиль, в котором доступ запрещен для всех процессов.Разрешенные или заблокированные операции/команды:
В профилях allow|privileged или baseline можно указать список разрешенных или заблокированных команд, и они будут применены.
--protection-allow: список разрешенных операций, разделенных запятыми. Действителен в профиле baseline, полезен для приложений, которые слишком специфичны и выполняют привилегированные операции. Это уменьшит использование профиля allow | privileged, поэтому вместо использования профиля мы можем указать и добавить набор разрешенных команд для определения таких приложений в каждом конкретном случае.Примеры безопасности BPF см. в примерах конфигурации bpflock
bpflock требует следующего:
Версия ядра Linux >= 5.13 со следующей конфигурацией:
CONFIG_BPF_SYSCALL=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO_BTF=y
CONFIG_KPROBES=y
CONFIG_LSM="...,bpf"
CONFIG_BPF_LSM=y
Очевидно, ядро с поддержкой BTF.
Если ваше ядро было скомпилировано с CONFIG_BPF_LSM=y, проверьте /boot/config-*, чтобы подтвердить, но при запуске bpflock выдается ошибка:
must have a kernel with 'CONFIG_BPF_LSM=y' 'CONFIG_LSM=\"...,bpf\"'"
Затем, чтобы включить BPF LSM, например в Ubuntu:
GRUB_CMDLINE_LINUX и сохраните.
"lsm=lockdown,capability,yama,apparmor,bpf"
GRUB_CMDLINE_LINUX="lsm=lockdown,capability,yama,apparmor,bpf"
sudo update-grub2
Для запуска с профилем по умолчанию allow или privileged (наименее безопасный профиль):
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
Для регистрации и ограничения безфайлового выполнения бинарных файлов запустите с:
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
При работе в профиле restricted в журнале контейнера будет отображаться:
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
Запуск в профиле restricted может нарушить работу, поэтому профиль по умолчанию — allow.
Для применения защиты модулей ядра запустите с переменной окружения BPFLOCK_KMODLOCK_PROFILE=baseline или 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
Пример:
$ 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
Для применения блокировки образа ядра запустите с переменной окружения 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
Для применения ограничения BPF запустите с переменной окружения BPFLOCK_BPFRESTRICT_PROFILE=baseline или 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
Пример запуска в другом пространстве имен pid и network с использованием 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
Запуск с профилем -e "BPFLOCK_BPFRESTRICT_PROFILE=restricted" запретит bpf для всех:
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
Передача конфигурации в виде привязок (bind mounts) может быть выполнена с помощью следующей команды.
Предполагая, что конфигурации bpflock.yaml и профилей bpf.d находятся в текущем каталоге внутри папки bpflock, тогда мы можем просто использовать:
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
Переменные окружения также можно передавать с помощью файлов через --env-file. Все параметры могут быть переданы как переменные окружения в формате BPFLOCK_$ИМЯ_ПЕРЕМЕННОЙ=ЗНАЧЕНИЕ.
Пример запуска с переменными окружения в файле:
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
Файлы документации можно найти здесь.
bpflock использует docker BuildKit для сборки и Golang для выполнения некоторых проверок и запуска тестов. bpflock собирается внутри контейнера Ubuntu, который загружает стандартный пакет golang.
Выполните следующее, чтобы собрать docker-контейнер bpflock:
git submodule update --init --recursive
make
BPF-программы собираются с использованием libbpf. Используемый образ docker — Ubuntu.
Если вы хотите собирать только BPF-программы напрямую без использования docker, то в 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
Затем выполните:
make bpf-programs
В этом случае сгенерированные программы будут находиться в каталоге ./bpf/build/...
bpflock использует множество ресурсов, включая исходный код из проектов Cilium и bcc.
Компоненты пользовательского пространства bpflock лицензированы в соответствии с Apache License, Version 2.0. BPF-код, где это указано, лицензирован в соответствии с General Public License, Version 2.0.
privilegedbaseline--protection-block: список заблокированных операций, разделенных запятыми. Действителен в профилях allow|privileged и baseline, позволяет ограничить доступ к некоторым функциям без использования полного профиля restricted, который может нарушить работу некоторых специфических приложений. Использование профилей baseline или privileged открывает доступ к большинству функций Linux, но с опцией --protection-block можно заблокировать часть этого доступа.