2. BPF在攻防中的应用
hook 系统调用和用户空间函数调用
操作用户空间数据结构
修改系统调用返回值
调用 system() 创建新进程(bpftrace内置特性)
某些 BPF 程序可以直接操作硬件设备(如网卡)
针对 BPF 代码的供应链攻击的可能性
配合安全检测工具使用(例如,hook bpf自身)
eBPF 几乎可以实现内核态 Rootkit 所有的隐藏功能,一般的内核模块的挂钩系统调用、虚拟文件系统,eBPF 程序可以使用不同的跟踪点程序类型完成相同功能。
eBPF 利用可以分为两个方面,网络侧和系统侧,分别通过网络类型程序和跟踪点类型程序实现,端口敲门、链路控制、权限提升、隐藏恶意程序行为等。

2.2 系统侧
在系统侧,一般 BPF 使用跟踪类型的程序,对系统调用的入口处进行跟踪,可以篡改发送给内核的函数参数,在系统调用的退出处可以篡改内核的返回值,触发内核 eBPF 后可以发送 event 事件到用户态程序。
在 entry 系统调用处,监测发送给内核的参数
在 exit 系统调用处,监测内核的返回值

而且由于可以监测到传递至系统调用的参数,那么就可以只针对特定进程名或进程号进行劫持。比如,通过 bpf_get_current_comm,只对 sudo 进程进行处理。

如果参数或返回值是指向用户空间内存的指针,则可以通过两个 eBPF 辅助函数进行读写。
bpf_probe_read_user
bpf_probe_write_user

BPF 实现恶意利用(包括但不限于):
隐藏进程/文件等恶意程序行为
可以根据:进程 ID、进程名称、用户名、函数参数、函数返回,来执行拦截或修改系统调用和返回值:kill、waitpid、openat、...
隐藏我们的 BPF 程序本身:map、程序
通过篡改 /proc/[pid] 文件夹的内容来隐藏特定进程
当程序调用 execve 劫持执行时更改可执行文件
覆盖敏感文件的内容
将用户添加到 /etc/passwd
从lsmod隐藏内核模块
……
比如,通过篡改 /proc/[pid] 文件夹的内容来隐藏特定进程。
比如,从 lsmod 隐藏内核模块。
eBPF 与传统的内核态 Hook 或 Kprobe 不同,使用跟踪点(tracepoint)的 eBPF 程序不会改变函数的地址或代码,因此部分 HIDS 无法感知,用户空间和内核之间的 eBPF 程序。
是可以从三个方面进行检测和防御:

3.1 禁用BPF
当业务场景不使用 BPF 特性时,可以直接禁用 BPF。
/proc/sys/kernel/unprivileged_bpf_disabled,可以开启或禁用 BPF。
值为0表示允许非特权用户调用 BPF
值为1表示禁止非特权用户调用 BPF,且该值不可再修改,只能重启后修改
值为2表示禁止非特权用户调用 BPF,可以再次修改为0或1

或者修改内核选项,重新编译内核,禁用 BPF。
CONFIG_BPF=y
CONFIG_BPF_SYSCALL=y
CONFIG_BPF_JIT=y
CONFIG_HAVE_EBPF_JIT=y
CONFIG_BPF_EVENTS=y
CONFIG_FTRACE_SYSCALLS=y
……
3.2 监控BPF系统调用
比较有效的方式是监控 BPF 系统调用,只有受信任的程序才允许使用 eBPF。
可以通过内核模块提前挂钩 BPF 系统调用,监控之后的 BPF 系统调用情况,阻止新的 eBPF 程序的加载。

也可以通过 eBPF 程序,监控 BPF 系统调用,对后续的 BPF 调用进行判断是否允许加载。比如,使用 bpftrace 对 BPF 系统调用进行检测。

3.3 kprobe监控以及内核代码完整性校验
使用内核探针(Kprobe)类型的 eBPF 程序会改变函数的地址或代码,因此是可以通过 kprobes 调用和内核完整性校验进行检测。
对内核 kprobe list 进行读取检测,检测是否存在异常的内核函数探针,

对内核代码区域进行完整性校验,如果发生改变,进行告警。

3.4 bpftool检测BPF程序
bpftool 可以帮助我们检测系统中是否存在 BPF 程序,比如,显示已加载的BPF 程序,比如,map、perf、net 等类型,而且可以 dump 出 BPF 字节码进行分析。
bpftool prog show

bpftool map show

bpftool net show

bpftool btf dump id xx

……
部分攻击者可能会对抗bpftool,执行bpftool时杀掉bpftool进程。最简单的反对抗方法是重命名bpftool文件后执行。
3.5 ip或tc检测BPF程序
ip或tc程序是针对网络类型的BPF程序,ip命令可以发现网卡上是否存在xdp程序,并且卸载xdp程序。tc程序可以发现tc分类器类型的bpf程序。
ip link show
ip link set dev ens0 xdp off
tc filter show dev ens0 [ingress|egress]

3.6 bpflist-bpfcc检测BPF程序
bpflist-bpfcc -vv 命令可以看到当前服务器运行的部分 BPF 程序列表。


3.7 eBPF IDA pro
BPF程序也是 ELF 文件,使用 LLVM + Libbpf 编译的程序很容易分辨,设置的跟踪点名称会以相同名称显示在 ELF 节中。


使用 bpftool + Libbpf 编译的程序,跟踪点名称则加载到 .rodata,需要手动提取。提取后的数据,可以通过 IDA eBPF 插件解析为 BPF 字节码,显示BPF 指令。

3. 最后
植入内核态 Rootkit 可能带来极大的风险
eBPF 消除了这种风险,使运行安全、可移植的 Rootkit 成为可能
eBPF Hook 系统调用和用户空间函数调用,修改系统调用返回值
eBPF 程序可以直接操作硬件设备(如网卡)
eBPF 程序重启后,需要重新加载执行
利用 eBPF 开发 HIDS,检测 eBPF 利用(例如ehids)
reference
https://www.ebpf.top/post/ebpf_c_env/
https://www.ebpf.top/post/offensive-bpf-bpftrace/
https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git/commit/?id=ec24704492d8
https://www.cnblogs.com/charlieroro/p/14244276.html
https://www.cnxct.com/ebpf-rootkit-how-boopkit-works/
https://embracethered.com/blog/posts/2021/offensive-bpf-bpftrace/
https://www.brendangregg.com/BPF/bpftrace-cheat-sheet.html
https://github.com/xdp-project/xdp-tools/releases/tag/v1.2.3
https://www.libhunt.com/r/bad-bpf
https://blog.tofile.dev/2021/08/01/bad-bpf.html
https://www.blackhat.com/us-21/briefings/schedule/#with-friends-like-ebpf-who-needs-enemies-23619