On Bypassing eBPF Security Monitoring(译文)

LeeH 2022-10-18 09:56:00

前言

Extended Berkeley Packet Filter(eBPF)是一种内核技术(从 Linux 4.x 开始),它允许程序在无需更改内核源代码,或添加额外模块的情况下运行。你可以将其视为 Linux 内核中的轻量级沙箱虚拟机(VM),程序员可以在其中运行 BPF 字节码,从而利用特定的内核资源,近几年eBPF的发展越来越火热,对应的,他的安全问题也是一项不可忽视的关注点

在Black Hat 2021的会议中,Guillaume Fournier的分享, 介绍了eBPF如何被恶意利用,包括如何构建一个rootkit、如何利用, 并构建了对应的检测代码

同样的在DEF CON29会议上,Pat Hogan也提到了利用案例, 介绍了eBFP rootkit的应用场景,包括网络、运行时等场景,以及如何检测eBPF被恶意利用等, 也有着公开的检测代码

最近,我关注到了,一种对eBPF的安全检测的一个Bypass思路,分享给大家

正文

当今有许多可用的安全解决方案依赖于 Linux 内核的 Extended Berkeley Packet Filter (eBPF) 功能来监控内核功能。各种原因推动了最新监测技术的这种范式转变。其中一些是出于在日益以云为主导的世界中的性能需求等。 Linux 内核始终具有内核跟踪功能,例如kprobes (2.6.9), ftrace (2.6.27 和更早之前), perf (2.6.31), or uprobes (3.5),但使用 BPF 最终可以运行内核级别事件程序并因此修改系统的状态,而无需编写内核模块。这对于任何希望破坏系统并且未被发现的攻击者具有巨大的影响,从而开辟了新的研究和应用领域。如今,基于 eBFP 的程序用于 DDoS 缓解、入侵检测、容器安全和一般可观察性。

2021 年,Teleport 引入了一项名为增强会话记录的新功能,以弥补 Teleport 审计能力中的一些监控差距。报告的所有问题均已按照其 2021 年第四季度公开报告中的描述及时修复、缓解或记录。下面你可以看到我们如何设法绕过基于 eBPF 的控制的说明,以及关于红队或恶意行为者如何逃避这些新的入侵检测机制的一些想法。这些技术通常可以应用于其他目标,同时试图绕过任何基于 eBPF 的安全监控解决方案

eBPF 如何工作的简述

image-20221015104331837.png

扩展的 BPF 程序是用高级语言编写的,并使用工具链编译成 eBPF 字节码。用户模式应用程序使用 bpf() 系统调用将字节码加载到内核中,其中 eBPF 验证程序将执行许多检查以确保程序在内核中“安全”运行。这个验证步骤很关键——eBPF 为非特权用户公开了一条在 ring 0 中执行的路径。由于允许非特权用户在内核中运行代码是一个成熟的攻击面,过去的几项研究都集中在本地特权利用 (LPE) ,我们不会在这篇博文中介绍。程序加载后,用户模式应用程序将程序附加到一个hook点,该hook将在某个hookevent)被命中(occurs)时触发执行。在某些情况下,该程序也可以被 JIT 编译成本地汇编指令。用户模式应用程序可以使用 eBPF 映射和 eBPF 辅助函数与在内核中运行的 eBPF 程序进行交互并从中获取数据。

常见的缺点和潜在的绕过(这里是重点)

1. 了解捕获了哪些事件

虽然 eBPF 很快(比 auditd 快得多),但由于性能原因,有很多有趣的领域无法合理地使用 BPF 进行检测。根据安全监控解决方案最想保护的内容(例如,网络通信、执行、文件系统操作),可能存在过度探测可能导致性能开销促使开发团队忽略它们的区域。这取决于端点代理的设计和实现方式,因此仔细审核 eBPF 程序的代码安全性至关重要。

1.1 执行绕过

例如,一个简单的监控解决方案可以决定只hook execve 系统调用。与普遍的看法相反,多个基于 ELF 的类 Unix 内核不需要磁盘上的文件来加载和运行代码,即使它们通常需要一个文件。实现这一点的一种方法是使用一种称为反射加载的技术。反射加载是一种重要的利用后技术,通常用于避免检测并在锁定环境中执行更复杂的工具。 execve() 的手册页指出:“execve() 执行文件名指向的程序……”,并接着说“调用进程的文本、数据、bss 和堆栈被程序的覆盖加载”。这种覆盖不一定构成 Linux 内核必须垄断的东西,不像文件系统访问或其他任何东西。正因为如此,execve() 系统调用可以在用户空间中以最小的难度被模仿。因此,创建一个新的过程映像很简单:

  • 清理地址空间;
  • 检查并加载动态链接器;
  • 加载二进制文件;
  • 初始化堆栈;
  • 确定入口点
  • 转移执行控制权

按照这六个步骤,可以创建和运行一个新的过程映像。自 2004 年首次报告该技术以来,该过程现已由 OTS 后开发工具开创并简化。正如预期的那样,hooking execve 的 eBPF 程序将无法捕捉到这一点,因为这个自定义用户态 exec将有效地将当前地址空间中的现有进程映像替换为新的进程映像。在此,用户态 exec 模仿系统调用 execve() 的行为。但是,因为它在用户态中运行,所以描述进程映像的内核进程结构保持不变。

其他系统调用可能不受监控并降低监控解决方案的检测能力。其中一些是 cloneforkvforkcreatexecveat

如果 BPF 程序是不成熟的并且信任引用正在执行的文件的完整路径的 execve 系统调用参数,则可能存在另一个潜在的绕过。攻击者可以在不同位置创建 Unix 二进制文件的符号链接并执行它们——从而篡改日志。

1.2 网络绕过

hook所有与网络相关的系统调用可能会产生一系列问题。一些监控解决方案可能只想hook EGRESS 流量,而攻击者仍然可以将数据发送到滥用其他网络敏感操作的非允许主机(参见 linux/security/apparmor/include/audit.h:78 上的 aa_ops)相关到 INGRESS 流量:

  • OP_BINDbind() 函数应将本地套接字地址分配给由没有分配本地套接字地址的描述符套接字标识的套接字。
  • OP_LISTENlisten() 函数应将由 socket 参数指定的连接模式套接字标记为接受连接。
  • OP_ACCEPTaccept() 函数将提取待处理连接队列中的第一个连接,创建一个与指定套接字具有相同套接字类型协议和地址族的新套接字,并为该套接字分配一个新的文件描述符。
  • OP_RECVMSGrecvmsg() 函数应从连接模式或无连接模式套接字接收消息。
  • OP_SETSOCKOPTsetsockopt() 函数应在 level 参数指定的协议级别将 option_name 参数指定的选项设置为与套接字参数指定的文件描述符关联的套接字的 option_value 参数指向的值。攻击者感兴趣的选项是 SO_BROADCASTSO_REUSEADDRSO_DONTROUTE

一般来说,网络监控应该像 AppArmor 一样查看所有基于套接字的操作。

如果同一本地用户混合了受监控和不受监控的控制台会话,则受监控会话中的攻击者可能会利用打开的文件描述符和套接字将数据发送到受限制的主机。 2020 年,一些版本的 Linux 内核引入了一个新的系统调用来实现这一点,称为 pidfd_getfd。少数操作系统(如 Ubuntu)实现了 Yama 内核模块,该模块将文件描述符访问限制为仅限子父进程。 Github (TheZ3ro/fdstealer) 上提供了使用此功能的 PoC 代码。

image-20221015111809836.png

2. 延迟执行

如果只监控活动的控制台会话,eBPF 程序可能只存在于会话的时间跨度。通过延迟命令的执行(通过 sleeptimeoutsarvmstatinotifywaitatcron ...)并退出会话,可以完全规避解决方案。

3. 规避基于 cgroup 的范围事件监控

安全监控解决方案可能只对审计特定用户或cgroup感兴趣(例如在远程控制台会话的上下文中)。以 Teleport 为例,它通过将每个事件与控制组(尤其是 cgroupv2)的会话相关联来实现这一点。控制分组是 Linux 内核的一项功能,用于限制对一组进程的资源访问。它用于许多容器化技术(在幕后 Docker 为容器创建了一组命名空间和控制组),其特点是所有子进程都将保留父进程的 id。当 Teleport 启动 SSH 会话时,它首先会重新启动自己并将自己置于 cgroup 中。这不仅允许使用唯一 ID 跟踪该过程,还允许 Teleport 启动的所有未来过程。 Teleport 运行的 BPF 程序已更新为也发出执行它们的程序的 cgroup ID。 BPF 脚本检查 bpf_get_current_cgroup_id() 返回的值,只关心重要的会话 cgroup。最简单的逃避此审计策略的方法是更改您的 cgroup ID,但攻击者需要 root 才能实现此目的。干预 cgroupv2 伪文件系统或滥用 PAM 配置也是影响 cgroup/会话相关性的潜在机会。

另一种技术涉及由 初始化 重新分配。在 Teleport 的情况下,当会话产生的 bash 进程终止时,它的子进程成为孤立进程,并且 Teleport 进程终止其执行。当子进程成为孤儿时,操作系统可以在特定条件下(没有 tty、成为进程组组长、加入新进程会话)将其分配到不同的 cgroup。这允许攻击者绕过现有的限制。以下 PoC 是此设计的旁路示例:

  • 打开一个新的 eBPF 监控会话
  • 通过执行 tmux 命令启动 tmux
  • 按 CTRL+B 然后按 D 从 tmux 中分离
  • 杀死作为 tmux 父级的bash 进程
  • 通过执行 tmux attach重新附加到tmux进程。进程树现在看起来像这样:

image-20221015112310505.png

作为另一种攻击途径,利用机器上不同本地用户或者cgroupv2运行的进程(滥用其他守护进程、委托 systemd)也可以帮助攻击者规避这一点。这方面显然取决于托管监控解决方案的系统。防止这种情况是很棘手的,因为即使 PR_SET_CHILD_SUBREAPER设置为确保后代不能将自己重新设置为init,如果祖先reaper死亡或被杀死 (DoS),那么该服务中的进程可以逃脱他们的 cgroup“容器” ”。此特权服务进程的任何妥协(或它的渎职行为)都允许它杀死其层次结构管理器进程并逃脱所有控制。

4. 内存限制和事件丢失

BPF 程序有很多限制。只为 eBPF 程序保留了 512 字节的堆栈空间。变量将在执行开始时被提升和实例化,如果脚本试图转储系统调用参数或 pt-regs,它将很快耗尽堆栈空间。如果没有设置指令限制的解决方法,则可以将脚本推送到检索太大而无法放入堆栈的东西,当执行变得复杂时很快就会失去可见性。但即使使用了变通方法(例如,当使用多个探测器来跟踪相同的事件但捕获不同的数据时,或者将您的代码拆分为使用程序映射相互调用的多个程序时)仍然有可能滥用它。 BPF 程序并不意味着永远运行,但它们必须在某个时候停止。例如,如果监控解决方案在 CentOS 7 上运行并试图捕获进程参数及其环境变量,则发出的事件可能有太多 argv和太多 envp。即使在这种情况下,您也可能会错过其中的一些,因为循环更早停止。在这些情况下,事件数据将被截断。需要注意的是,这些限制因运行 BPF 的内核以及端点代理的编写方式而异。

eBPF 的另一个特点是,如果不能足够快地消耗事件,它们会丢弃事件,而不是拖累整个系统的性能。攻击者可以通过生成足够数量的事件来填充性能环缓冲区并在代理读取数据之前覆盖数据来滥用此功能。

5. 永远不要相信用户空间

内核空间对pid 的理解与用户空间对pid的理解不同。如果 eBPF 脚本试图识别文件,正确的方法是获取 inode 号和device号,而文件描述符则没有那么有用。即使在这种情况下,探针也可能会遇到 TOCTOU 问题,因为它们会将数据发送到可以轻松更改的用户模式。如果脚本直接跟踪系统调用(使用 tracepointkprobe),它可能会被文件描述符卡住,并且可以通过玩弄当前工作目录和文件描述符来混淆执行(例如,通过组合fchdiropenat、和execveat)。

6. 滥用 seccomp-bpf 和内核差异的缺失

基于 eBPF 的监控解决方案应该通过使用 seccomp-BPF 在生成控制台会话之前永久放弃进行bpf() 系统调用的能力来保护自己。如果没有,攻击者将有能力使用bpf()系统调用来卸载用于跟踪执行的 eBPF 程序。 Seccomp-BPF使用 BPF 程序过滤任意系统调用及其参数(仅限常量,无指针解引用)。

使用内核时要记住的另一件事是,不能保证接口是一致和稳定的。如果 eBPF 程序未在经过验证的内核版本上运行,攻击者可能会滥用它们。通常,不同架构的条件编译对于这些程序来说非常复杂,您可能会发现特定内核的变体没有正确定位。使用seccomp-BPF 的一个常见缺陷是过滤系统调用号而不检查 seccomp_data->archBPF 程序参数。这是因为在任何支持多个系统调用调用约定的架构上,系统调用号可能会根据特定调用而有所不同。如果不同调用约定中的数字重叠,则可能会滥用过滤器中的检查。因此,确保 seccomp-BPF 过滤器规则考虑到每个新支持的架构的bpf()调用差异非常重要。

7.干扰代理

与上面的方法类似,可能会以不同方式干扰 eBPF 程序加载,例如针对 eBPF 编译器库(BCClibbcc.so)或调整其他共享库预加载方法以篡改合法二进制文件的行为解决方案,最终执行有害操作。如果攻击者成功更改解决方案的主机环境,他们可以在 LD_LIBRARY_PATH 前面添加一个目录,他们在其中保存具有相同libbcc.so名称的恶意库并导出所有使用的符号(以避免运行时链接错误) .当解决方案启动时,它会与恶意库链接,而不是合法的密件抄送库。对此的防御可能包括使用静态链接的程序、使用完整路径链接库或将程序运行到受控环境中。

来源

该篇翻译自

https://blog.doyensec.com/2022/10/11/ebpf-bypass-security-monitoring.html

评论

L

LeeH

这个人很懒,没有留下任何介绍

twitter weibo github wechat

随机分类

逻辑漏洞 文章:15 篇
SQL注入 文章:39 篇
安全开发 文章:83 篇
密码学 文章:13 篇
前端安全 文章:29 篇

扫码关注公众号

WeChat Offical Account QRCode

最新评论

Article_kelp

因为这里的静态目录访功能应该理解为绑定在static路径下的内置路由,你需要用s

N

Nas

师傅您好!_static_url_path那 flag在当前目录下 通过原型链污

Z

zhangy

你好,为什么我也是用windows2016和win10,但是流量是smb3,加密

0

0x0dee

标题写错了,是ASX to MP3 3.1.3.7 - '.m3u' Local

K

k0uaz

foniw师傅提到的setfge当在类的字段名成是age时不会自动调用。因为获取

目录