hook 系统调用和用户空间函数调用
操作用户空间数据结构
修改系统调用返回值
调用 system() 创建新进程(bpftrace内置特性)
某些 BPF 程序可以直接操作硬件设备(如网卡)
针对 BPF 代码的供应链攻击的可能性
eBPF 几乎可以实现内核态 Rootkit 所有的隐藏功能,一般的内核模块的挂钩系统调用、虚拟文件系统,eBPF 程序可以使用不同的跟踪点程序类型完成相同功能。
eBPF 利用可以分为两个方面,网络侧和系统侧,分别通过网络类型程序和跟踪点类型程序实现,端口敲门、链路控制、权限提升、隐藏恶意程序行为等。
在系统侧,一般 BPF 使用跟踪类型的程序,对系统调用的入口处进行跟踪,可以篡改发送给内核的函数参数,在系统调用的退出处可以篡改内核的返回值,触发内核 eBPF 后可以发送 event 事件到用户态程序。
在 entry 系统调用处,监测发送给内核的参数
而且由于可以监测到传递至系统调用的参数,那么就可以只针对特定进程名或进程号进行劫持。比如,通过 bpf_get_current_comm,只对 sudo 进程进行处理。
如果参数或返回值是指向用户空间内存的指针,则可以通过两个 eBPF 辅助函数进行读写。
bpf_probe_read_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,且该值不可再修改,只能重启后修改
或者修改内核选项,重新编译内核,禁用 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,执行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
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 程序重启后,需要重新加载执行
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