
bpflock - 用于锁定和审计 Linux 机器的 eBPF 驱动安全工具。
注意:bpflock 目前处于 实验阶段,可能会出问题,选项和安全语义可能会发生变化,部分 BPF 程序将更新为使用 Cilium ebpf 库。
bpflock 利用 eBPF 强化 Linux 安全。通过限制对各种 Linux 功能的访问,bpflock 能够减少攻击面并阻止一些众所周知的攻击技术。
只有像容器管理器、systemd 以及运行在宿主机 pid 和网络命名空间 中的其他容器/程序才被允许访问完整的 Linux 功能;运行在自身命名空间中的容器和应用程序将受到限制。
如果 bpflock bpf 程序在 restricted 配置下运行,那么所有程序/容器(包括特权容器)的访问都将被拒绝。
bpflock 通过利用多种安全特性(包括 Linux 安全模块 + BPF)来保护 Linux 机器。
架构与安全设计说明:
bpflock 提供多种安全保护,可分为以下几类:
文件系统保护
网络保护
bpflock 保持安全语义简单。它支持三个 全局 配置,广泛覆盖安全范围,并可限制对特定 Linux 功能的访问。
profile:这是全局配置,可应用于每个 bpf 程序,取以下值之一:
allow|none|privileged:它们相同,定义最低安全级别的配置。在此配置下,访问将被记录并允许所有进程。适用于记录安全事件。baseline:限制性配置,拒绝所有进程的访问,但运行在宿主机命名空间中的特权应用程序和容器除外,或在 bpflock_cgroupmap bpf 映射中定义了 cgroup 允许配置的进程。restricted:高度限制性配置,拒绝所有进程的访问。允许 或 阻止 的操作/命令:
在 allow|privileged 或 baseline 配置下,可以指定允许或阻止的命令列表并应用。
--protection-allow:逗号分隔的允许操作列表。仅在 baseline 配置下有效,适用于非常特殊且执行特权操作的应用程序。这将减少使用 allow | privileged 配置的需求:我们可以使用 baseline 配置并添加一组允许的命令,从而为这类应用提供逐一定义。--protection-block:逗号分隔的阻止操作列表。在 allow|privileged 和 baseline 配置下均有效,允许限制对某些功能的访问,而无需使用可能破坏特定应用的 restricted 完整配置。使用 baseline 或 privileged 配置会开放对大多数 Linux 功能的访问,但通过 --protection-block 选项可以阻止部分访问。有关 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\"'"
那么,以 Ubuntu 为例启用 BPF LSM:
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