Linux | eBPF技术的Rootkit攻防 (二)
2022-11-5 12:1:18 Author: TahirSec(查看原文) 阅读量:82 收藏

2. BPF在攻防中的应用

回顾 BPF 在攻防中的应用
BPF 很有趣,因为 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
比如,挂钩 read 系统调用,读取数据,篡改数据。

BPF 实现恶意利用(包括但不限于):

  • 隐藏进程/文件等恶意程序行为

      • 可以根据:进程 ID、进程名称、用户名、函数参数、函数返回,来执行拦截或修改系统调用和返回值:kill、waitpid、openat、...

      • 隐藏我们的 BPF 程序本身:map、程序

      • 通过篡改 /proc/[pid] 文件夹的内容来隐藏特定进程

  • 当程序调用 execve 劫持执行时更改可执行文件

  • 覆盖敏感文件的内容

  • 将用户添加到 /etc/passwd

  • 从lsmod隐藏内核模块

……

比如,通过篡改 /proc/[pid] 文件夹的内容来隐藏特定进程。

比如,从 lsmod 隐藏内核模块。

3. eBPF利用检测防御思路

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


文章来源: http://mp.weixin.qq.com/s?__biz=MzkzNjIwMzM5Nw==&mid=2247485089&idx=1&sn=4a2790e6f38954da0b385bb1ce226516&chksm=c2a3034bf5d48a5d408ceeeb2132d654a4f4e0b7a6b57f44d6010a1dbed9242f49561a06eea3#rd
如有侵权请联系:admin#unsafe.sh