原文:https://www.outflank.nl/blog/2024/06/03/edr-internals-macos-linux/
前言:
许多公共博客和会议演讲都涵盖了 Windows 遥测源,如内核回调和 ETW,但很少有人提到 macOS 和 Linux 的等效物。虽然大多数安全专业人员可能不会对这种缺乏报道感到惊讶,但不应忽视这些平台。例如,使用 macOS 的开发人员通常拥有特权云帐户或访问源代码等知识产权。Linux 服务器可能托管敏感数据库或面向客户的应用程序。防御者必须对他们用于这些系统的工具有信心,而攻击者必须了解如何规避它们。这篇文章深入研究了 macOS 和 Linux 上的端点安全产品,以了解它们的功能并识别弱点。
端点检测和响应 (EDR) 代理由多个传感器组成:从一个或多个遥测源收集事件的组件。代理将原始遥测数据格式化为标准格式,然后将其转发到日志聚合器。EDR 遥测数据不仅会通知防病毒软件等工具,还会通知人们手动搜索网络中的威胁。
这篇文章不应被视为遥测源或 EDR 实现的完整列表。相反,在对一些最流行的 macOS 和 Linux 代理进行逆向工程时,我们得出了以下观察结果。Outflank 在 macOS 14.4.1(Sonoma)和 Linux 5.14.0(Rocky 9.3)上测试了每种产品的最新版本。在回顾了之前的研究之后,作者将描述 macOS 和 Linux 的相关安全组件,介绍他们对流行 EDR 产品的理解,然后总结出使用这些知识攻击 EDR 的案例研究。
值得注意的 EDR 功能
尽管每种产品都有自己检测最新威胁的“秘密公式”,但几乎所有 EDR 代理都会收集以下事件类型:
● 身份验证尝试
● 进程创建和终止
● 文件访问、修改、创建和删除
● 网络流量
Outflank 的研究主要集中在这些事件上,但这篇文章也将介绍其他特定于操作系统的遥测数据
即便如此,这些项目仍未完全复制流行的 EDR 代理的功能。虽然每个项目都可能收集商业产品使用的遥测数据子集,但这些项目似乎都没有相同的覆盖范围。
遥测源 – macOS
不支持的选项
在研究 macOS 内部结构时,人们可能会发现商业产品未使用的有前途的安全组件。例如,许多人认为内核扩展(KEXT) 是 EDR 代理的事实上的传感组件,直到 Catalina (2019) 完全淘汰它们。Michael Cahyadi关于从内核扩展过渡到现代替代方案的帖子记录了从这些框架迁移所需的工作。
同样,现代 macOS(2016 及以上版本)实现了一个标准化的日志系统,称为统一日志记录。日志按子系统(例如)分类,可以使用或应用程序com.apple.system.powersources.source查看。虽然统一日志数据非常适合调试,但日志受到私有授权()的限制,因此第三方 EDR 代理无法使用它们。/usr/bin/logConsolecom.apple.private.logging.stream
端点安全 API
Apple 现在建议使用Endpoint Security (ES) API 来记录 EDR 代理所需的大多数事件:
● 身份验证尝试
● 进程创建和终止
● 文件访问、修改、创建和删除
Apple 文档中的 ES 事件类型完整列表遵循标准格式:。
ES_EVENT_TYPE_<RESPONSE TYPE>_<EVENT TYPE NAME>
“响应类型”可以是NOTIFY或AUTH,具体取决于 ES 客户端是否必须授权操作。“事件类型名称”描述每个事件。(以下部分将讨论示例。)
对于那些希望编写 ES API 客户端的人来说,有很多开源示例,但在现代 macOS 上执行它们需要开发人员使用受限权利签署其可执行文件或在目标系统上禁用 SIP 。
ES API 中明显缺少网络事件。相反,EDR 代理可以利用额外的传感器,通过NetworkExtension框架捕获事件。
随着 Apple 弃用内核扩展,可以使用 ES API 和 NetworkExtension 框架完全从用户模式收集事件。这与严重依赖内核模式传感器的 Windows 和 Linux 不同。
分析 ES API 客户端
Red Canary Mac Monitor是一款免费的闭源 ES 客户端。它使用系统扩展,因此客户端必须嵌入到 中的应用程序包中Contents/Library/SystemExtensions/。在这种情况下,可以使用实用程序列出包的权限codesign。
输出属性列表将根据目标系统扩展而有所不同,但所有 ES 客户端都必须具有com.apple.developer.endpoint-security.client权利。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "https://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.application-identifier</key>
<string>UA6JCQGF3F.com.redcanary.agent.securityextension</string>
<key>com.apple.developer.endpoint-security.client</key>
<true/>
<key>com.apple.developer.team-identifier</key>
<string>UA6JCQGF3F</string>
<key>com.apple.security.application-groups</key>
<array>
<string>UA6JCQGF3F</string>
</array>
</dict>
</plist>
libEndpointSecurity.dylib ES 客户端必须使用和导出的两个函数初始化 API es_new_client。es_subscribe后者特别有趣,因为它向 ES API 指示客户端应该接收哪些事件。一旦发现感兴趣的客户端,就可以使用Frida对其进行检测(禁用 SIP后)。该es_subscribe函数包含两个感兴趣的参数:事件数(event_count)和指向事件 ID 列表的指针(events)。
有了这些信息,就可以使用 Frida 注入目标系统扩展进程并进行挂钩,es_subscribe以了解它订阅了哪些事件。该函数很可能只会在系统扩展启动时被调用,因此分析 EDR 代理可能需要一些创造性思维。Mac Monitor 使这一步变得简单,因为运行时 GUI 可以更新事件列表。
在 Red Canary Mac Monitor 中更改目标 ES 事件
Outflank 上传了一个简单的Frida 脚本(基于 Mac Monitor wiki和脚本)来挂钩es_subscribe和打印事件列表,以及一个用于创建或注入进程的示例Python 脚本。
使用 Frida 检索 ES API 事件
检查 ES 事件类型
即使有事件类型列表,ES 客户端可用的实际数据可能也不清楚。Outflank 发布了一个名为ESDump的开源工具,它可以订阅任何当前可用的事件类型并将 JSON 格式的事件输出到stdout。
事件类型列表在config.h编译时定义。例如,以下配置将订阅上一节中选择的事件类型。
ESDump 配置
编译该程序,然后将其复制到禁用 SIP 的macOS 系统。ESDump 没有任何参数。
转储端点安全事件
ESDump 使用审计令牌来检索相关进程和用户的 ID。该程序解析进程和用户名以丰富原始数据。
根据审计令牌解析进程和用户名
网络扩展框架
与 ES API 不同,NetworkExtension 框架没有预定义的事件类型。相反,代理必须对各种框架类进行子类化才能监控网络流量。每个框架类都需要不同的授权。相关授权可深入了解可能的用例:
● DNS 代理– 代理 DNS 查询并解析来自系统的所有请求。
● 内容过滤器– 允许或拒绝网络连接。适用于数据包检查和防火墙应用程序。
● 数据包隧道— 适用于 VPN 客户端应用程序。
除了 DNS 请求和响应数据之外,提供程序还可以访问有关源进程的元数据,包括其签名标识符和应用程序审计令牌。内容过滤器提供程序还可以访问进程审计令牌,如果系统进程代表应用程序建立网络连接,则该令牌与应用程序审计令牌不同。在这两种情况下,这些属性足以找到原始进程和用户 ID,以将网络扩展数据与 ES API 事件关联起来。
分析网络扩展
发现代理实现的网络扩展提供程序很简单,因为它们每个都需要单独的授权。Objective -See 的DNSMonitor是一个开源 DNS 代理提供程序。它使用系统扩展,因此提供程序必须嵌入到其应用程序包中Contents/Library/SystemExtensions/。
打开系统扩展包
在系统扩展包中,将有一个文件,其中Contents/Info.plist包含有关其权利的信息。NetworkExtension应该存在该键,并有一个NEProviderClasses列出每个提供程序实现的子键。
<key>NetworkExtension</key>
<dict>
<key>NEMachServiceName</key>
<string>VBG97UB4TA.com.objective-see.dnsmonitor</string>
<key>NEProviderClasses</key>
<dict>
<key>com.apple.networkextension.dns-proxy</key>
<string>DNSProxyProvider</string>
</dict>
</dict>
每种提供程序类型还将突出显示相关类的名称。这些信息足以开始使用Hopper等工具逆向扩展。
DNS 代理提供程序类方法
创建网络扩展
虽然了解 macOS 网络扩展实现的提供程序很有价值,但还需要更多内容来了解代理可用的数据。Outflank 发布了一个名为NEDump的开源工具,该工具实现了内容过滤器提供程序并将 JSON 格式的事件写入stdout。即使禁用 SIP,应用程序和系统扩展也必须签名,因此存储库包含已签名的发布二进制文件。在使用系统扩展时,必须将应用程序复制到/Applications/才能运行。执行 NEDump 并开始接收事件数据不需要任何参数。
转储内容过滤事件
遥测源 – Linux
虽然 Linux 组件的弃用频率低于 macOS 组件,但大多数 Linux EDR 代理都具有可比的现代实现。例如,Auditd可以为EDR 代理提供必要的遥测,但较新的替代方案具有更好的性能。此外,一次只有一个程序可以订阅 Auditd,这意味着代理可能会与其他软件冲突。这两个原因都是最常见的 EDR 投诉,这可能解释了为什么 Outflank 没有观察到任何默认使用这些方法的产品。
内核函数跟踪
所观察到的代理均使用内核函数跟踪作为其主要遥测源。Linux 提供了几种“挂钩”内核函数以检查其参数和上下文的方法。流行的 EDR 代理使用了以下跟踪方法:
● Kprobes 和 Return Probes – 客户端解析的任何内核函数(或地址)都可使用内核探测器进行跟踪。函数解析需要内核符号可用,并且可能需要内核版本甚至发行版使用不同的地址。由于编译时优化,目标函数甚至可能不可用。
● 跟踪点– “跟踪点”是添加到 Linux 内核中各种函数的函数调用,可在运行时挂接。它们的工作原理与 kprobes 类似,但速度更快,并且不需要函数解析。但是,某些目标函数可能没有跟踪点。
○ 原始跟踪点– “原始”跟踪点是任何非系统调用或 sys_enter/sys_exit 跟踪点的更高性能替代方案。这些挂钩还可以监视没有专用跟踪点的系统调用。
● 函数入口/出口探测器- Fentry 和 fexit 探测器的作用类似于跟踪点,但它们是由 GCC (-pg) 添加的。
内核模式编程
传统上,只有可加载内核模块 (LKM) 才能使用内核跟踪功能。LKM 类似于 Windows 驱动程序 - 崩溃可能会导致不可恢复的内核错误,从而引发类似的稳定性问题。Linux 内核 4.x 版本实现了伯克利数据包过滤器的“扩展”版本来解决这些问题,称为eBPF。此功能允许开发人员将小型可验证程序加载到内核中。eBPF 程序有实质性限制,但它们应该可以减轻基于 LKM 的传感器的稳定性风险。只有较新的 Linux 内核版本才支持 eBPF 和某些高级 eBPF 功能;客户可能没有在其环境中部署这些版本。这导致许多 EDR 供应商提供两个(或更多!)版本的 Linux 代理,每个版本都针对不同的内核版本。
Isovalent 的Liz Rice写了一本关于 eBPF 的优秀免费书籍。该公司还在其网站上为喜欢动手实践的人提供了一个免费的 eBPF 实验室。许多开源项目都展示了基于 eBPF 的跟踪的良好示例。这篇文章仅涵盖了每个代理的最新 eBPF 变体,但可以肯定的是,其他变体使用略微修改的 eBPF 或基于 LKM 的传感器收集了类似的信息。
分析 eBPF 程序
基于 eBPF 的传感器的两个组件可能有助于深入了解其实现:程序和映射。每个 eBPF 程序通常监视单个内核函数并使用映射与用户模式代理进行通信。Microsoft SysmonForLinux是一个有据可查的基于 eBPF 的开源监视工具。它使用多个跟踪点来监视进程、文件和网络事件。安装后,可以使用bpftool和命令检索当前加载的程序的完整列表bpftool prog list。结果通常包括不相关的程序,但 PID 可以识别相关结果,如下所示。
使用命令也可以访问 eBPF 程序的字节码bpftool prog dump。
此外,该bpftool map list命令还将检索完整的映射列表。同样,结果不相关,但 PID 描述了相关进程。
可以使用 访问地图的内容bpftool map dump。
检索每个程序的名称和字节码应该足以了解 eBPF 代理监视哪些功能。Outflank 创建了一个Bash 脚本来加快上述枚举。
传感器实现 – macOS
Outflank 在 macOS 上审查的 EDR 代理均具有类似的实现。以下部分旨在描述共性以及任何独特的方法。
身份验证事件
多个代理使用 收集身份验证数据getutxent,一些代理定期收集,另一些代理则响应特定事件。例如,一个代理使用Darwin 通知API 订阅com.apple.system.utmpx事件。Outflank 创建了另一个Frida 脚本,可与hook.py脚本一起使用来检查这些订阅。
其他代理订阅了以下 ES API 事件作为检查 utmpx 的触发器:
● 身份验证 – 最通用的身份验证事件。由正常登录、sudo 使用和某些远程登录生成。
● PTY_GRANT/CLOSE – 记录每个伪终端控制设备(shell 会话),包括本地终端和远程 SSH 连接。
● LW_SESSION_LOGIN/LOGOUT – 用户正常登录时发生。包括用户名和“图形会话 ID”,用于跟踪会话是否已结束。
● OPENSSH_LOGIN/LOGOUT – SSH 登录,包括失败的尝试。包括用户名和源地址。
● LOGIN_LOGIN/LOGOUT – 官方文档指出这些事件是针对每个“来自/usr/bin/login”的经过身份验证的登录事件生成的。作者无法生成此类事件。
流程事件
所有审查的 macOS 代理均订阅了以下进程事件类型。
● 执行
● 叉
● 出口
文件事件
所有经过审查的 macOS 代理均订阅了以下文件事件类型:
● 创造
● 打开
● 关闭
● 关联
● 解除链接
● 改名
● 山
● 克隆
● 设置模式
● 塞唐纳
● 设置标志
● 设置文本属性
订阅了其他事件类型的代理子集:
● 卸载
● 读取目录
● 删除文本
● 设置属性列表
● 重新安装
● 截短
● SETACL——尽管 macOS 使用 POSIX 文件权限,但它也使用访问控制列表(ACL)实现更细粒度的访问控制。
网络事件
所有经过审查的 macOS 代理都使用网络扩展来实现内容过滤器提供程序。有关内容过滤器可用数据的更多信息,请参阅前面的部分。
macOS 特定事件
每个 macOS 代理都订阅了以下特定于操作系统的事件子集:
● 远程线程_创建
● 进程暂停_恢复
● XP_MALWARE_DETECTED –内置 macOS 防病毒软件XProtect检测到恶意软件。补充事件类型 XP_MALWARE_REMEDIATED 表示恶意软件已被删除。
● GET_TASK_READ/INSPECT/NAME – 一个进程检索了另一个进程的任务控制/读取/检查/命名端口。Mach端口是 macOS 上的 IPC 机制。
● CS_INVALIDATED – 进程的代码签名状态现在无效,但该进程仍在运行。
● 信号——一个进程向另一个进程发送信号。
● UIPC_CONNECT – 连接到UNIX 域套接字的进程。
● BTM_LAUNCH_ITEM_ADD – 启动项已向后台任务管理公开。这包括常见的 macOS 持久性方法,如启动代理/守护程序和登录项。
传感器实现 – Linux
与 macOS 代理不同,Outflank 评测的 Linux 代理在实现方面具有更大的多样性。以下部分比较了各种产品所采用的方法。
身份验证事件
所审查的 Linux 代理的一部分挂钩了以下 PAM 功能:
● pam_authenticate– 包括失败的登录尝试。
● pam_open_session– 可能需要将其他事件与用户会话关联起来。
其他代理监视特定文件以捕获身份验证事件:
● /var/run/utmp
● /var/log/btmp– 包括失败的登录尝试。
流程事件
每个 Linux 代理都使用 的跟踪点(有些使用原始跟踪点)sched_process_exec。一款产品还在 上放置了一个 fentry 探测器finalize_exec,这是 调用的一个内部内核函数execve,但不清楚这能提供什么额外的信息。只有一些代理似乎使用跟踪点来监控fork使用情况。所有代理都使用、、或sched_process_fork上的跟踪点或 fentry 探测器来监控进程终止。sched_process_exittaskstats_exitsys_exit_setsidexit
文件事件
所审查的 Linux 代理的子集仅使用 fentry 探针或 kprobes 监控以下系统调用:
虽然一些代理完全依赖于系统调用,但其他代理仅跟踪一些代理并将 fentry 探测器或 kprobes 附加到以下内部内核函数:
网络事件
Outflank 观察到两种监控网络流量的通用策略。一些代理使用 kprobes 或 fentry 探针监控以下系统调用:
● socket
● bind
● accept
● setsockopt
● socketcall
其余代理没有监控网络系统调用,而是使用 fentry 或 kprobes 跟踪以下内部内核函数:
● sock_create
● inet_bind/inet6_bind
● inet_sendmsg/inet6_sendmsg
● inet_recvmsg/inet6_recvmsg
● inet_csk_accept
● inet_accept
● inet_listen
● tcp_close
● inet_release
● tcp_v4_connect/tcp_v6_connect
● inet_dgram_connect– UDP
● inet_stream_connect– TCP
● sock_common_recvmsg– 直流电源
● sk_attach_filter– 当SO_ATTACH_FILTER传递给 setsockopt 时调用。
Linux 特定事件
每个 Linux 代理都订阅了以下特定于操作系统的事件子集。
● security_bpf_map– 系统上的另一个程序可以访问或修改 eBPF 映射,但通常需要CAP_SYS_ADMIN或CAP_BPF功能。这意味着特权用户可能能够篡改传感器数据以掩盖甚至欺骗事件。作为回应,一些 EDR 代理会监视 eBPF 以保护其程序和映射。
● security_ptrace_access_check– 监控ptrace尝试。
● security_netlink_send– 监控netlink,这是用户模式进程和 Linux 内核之间共享数据的接口。
● madvise– 作者怀疑一些代理挂接了此系统调用来检测Dirty COW 等漏洞的利用。
案例研究:欺骗Linux系统调用
深入研究应用程序通常会激发安全研究人员发现导致意外但理想结果的逻辑缺陷。本节中重点介绍的示例仍然影响着流行的商业产品,作者希望激发该领域的更多社区研究。
幻影袭击
在 DEF CON 29 上,Rex Guo和Junyuan Zeng 利用了Falco 和 Tracee 的 TOCTOU 漏洞。他们对“Phantom Attack v1”的利用connect展示了欺骗某些网络 ( ) 和文件 ( ) 事件中的特定字段的能力openat。攻击需要三个单独的线程,如下所示。
幻影攻击步骤
系统调用需要稍微变化openat,但概念上是相似的。理想情况下,使用时间(处理页面错误后立即发生)发生在良性数据写入原始页面之前。实际上,他们的 POC 非常可靠,但需要提升权限。根据其手册,从 Linux 5.2 开始userfaultfd需要此CAP_SYS_PTRACE功能。延长 TOCTOU 窗口的另一种方法足以以普通用户身份利用此漏洞。
Falco 和 Tracee 使用内核函数跟踪,但它们容易受到攻击,因为它们跟踪的是系统调用而不是内部内核函数。直接评估用户模式提供的参数,包括指向调用进程分配的内存的指针。如上所述,一些 EDR 代理使用系统调用 kprobes 监控网络,这意味着它们可能容易受到相同的攻击。事实上,Outflank 的“Phantom Attack v1” POC分支connect在测试中对多种 EDR 产品有效。如下所示,原始代码经过修改,向目标(在本例中为 google.com)发出 HTTP GET 请求并输出响应。
总结:
这篇文章不应被视为遥测源或 EDR 实现的完整列表。相反,在对一些最流行的 macOS 和 Linux 代理进行逆向工程时,我们得出了以下观察结果。Outflank 在 macOS 14.4.1(Sonoma)和 Linux 5.14.0(Rocky 9.3)上测试了每种产品的最新版本。在回顾了之前的研究之后,作者将描述 macOS 和 Linux 的相关安全组件,介绍他们对流行 EDR 产品的理解,然后总结出使用这些知识攻击 EDR 的案例研究。
-
-
-
-
-
-
-
-
-
-
-