入侵的早期阶段通常包括初始访问、执行、持久性和命令和控制 (C2) 信标。当结构化威胁使用零日漏洞时,通常不会检测到前两个阶段。正如我们在 2020 年 SUNBURST 供应链入侵事件中看到的那样,识别高级攻击者留下的持久性机制通常具有挑战性且耗时。那么,我们是否可以通过查找其 C2 信标来在最初的几个小时或几天内检测到 SUNBURST?
信标检测的潜力在于,它可以作为早期预警系统,并有助于在执行后的最初几个小时或几天内发现新的持久性机制。这使得防御者可以在威胁参与者实现其目标之前中断或驱逐他们。因此,虽然我们通过检测 C2 信标并没有真正做到“在爆炸之前”,但我们可以通过减少攻击的整体影响,在攻击的结果中发挥重要作用。
在这篇博客中,我们将讨论使用 Elastic Stack 中的 Painless 和聚合构建的信标识别框架。该框架不仅可以帮助威胁猎人和分析师监控网络流量中的信标活动,还可以为他们提供有用的入侵指标 (IoC),以便开始调查。如果您没有 Elastic Cloud 集群但想试用我们的信标识别框架,您可以开始 14 天的 Elastic Cloud 免费试用。
信标 — 入门知识
企业的防御能力仅取决于其防火墙、防病毒软件、端点检测和入侵检测能力以及 SOC(安全运营中心)——由分析师、工程师、运营人员管理员等组成,他们全天候工作以确保组织安全。然而,恶意软件以多种不同的方式进入企业,并使用各种技术来逃避检测。如今,攻击者越来越多地使用的一种逃避检测的常见方法是使用 C2 信标作为其攻击链的一部分,因为它允许他们像正常用户一样融入网络。
在网络中,信标是一个术语,用于描述两个系统之间持续的通信节奏。在恶意软件的上下文中,信标是指恶意软件定期呼叫攻击者的 C2 服务器,以获取有关在受害者机器上执行的任务的进一步指令。恶意软件签到的频率以及用于通信的方法由攻击者配置。用于 C2 的一些常见协议是 HTTP/S、DNS、SSH 和 SMTP,以及常见的云服务(如 Google、Twitter、Dropbox 等)。使用通用协议和服务进行 C2 允许攻击者伪装成正常的网络流量,从而逃避防火墙。
虽然从表面上看,信标可能看起来类似于正常的网络流量,但它在时间和数据包大小方面具有一些独特的特征,可以使用标准的统计和信号处理技术对其进行建模。
以下是一个 Koadic C2 信标的示例,该信标使用 DLL 主机进程提供恶意有效负载。如您所见,有效负载以 10 分钟的间隔持续发出信标,并且源数据包大小和目标数据包大小几乎相同。
如果所有信标都像上面那样结构良好且可预测,那么捕获 C2 信标似乎是一项微不足道的任务。只需要寻找周期性和数据包大小的一致性即可。但是,如今的恶意软件并不那么简单。
如今,大多数复杂的恶意软件都会在信标间隔中添加“抖动”或随机性,从而使信号更难以检测。一些恶意软件作者还会使用更长的信标间隔。我们提出的信标识别框架考虑了对传统信标行为的一些难以捉摸的修改。
我们的方法
我们已经讨论了一些关于为什么和是什么的问题 — 在本节中,我们将深入探讨如何识别信标流量。在开始之前,必须注意信标仅仅是一种通信特征。从定义上讲,它既不好也不坏。虽然恶意软件现在确实严重依赖信标,但许多合法软件也表现出信标行为。
虽然我们已经努力减少误报,但应将此框架视为一种信标识别手段,以帮助减少威胁搜寻的搜索空间,而不是作为一种检测手段。也就是说,由该框架生成的指标与其他的 IoC 结合使用时,可能会用来检测恶意活动。
我们感兴趣的信标包括来自特定主机上单个运行进程到一个或多个外部 IP 的流量。鉴于恶意软件可能具有短(秒级)和长(小时或天级)的签到间隔,我们将把注意力限制在合理地适用于两者的时间窗口,并尝试回答以下问题:“我的环境中现在或最近有哪些信标?”我们还对框架的输入进行了参数化,以允许用户配置重要设置,例如时间窗口等。有关这方面的更多信息将在后续章节中介绍。
在处理大型数据集(例如企业的网络数据)时,您需要仔细考虑可以衡量的内容,这可以使您有效地扩展。扩展有几个方面,但就我们的目的而言,我们有以下要求
- 工作可以并行处理存储在不同机器上的不同数据分片
- 需要移动以计算所需内容的数据量必须保持在可管理的范围内。
已经提出了多种检测信标特征的方法,但并非所有方法都满足这些约束。例如,用于检测信标时间特征的一种流行选择是测量事件之间的间隔。事实证明,在大型数据集上使用此方法效率太低,因为无法跨多个分片处理事件。
在可扩展性的需求的驱动下,我们选择通过将要分析的时间窗口中的数据分桶来检测信标。我们收集每个存储桶中的事件计数和发送和接收的平均字节数。这些统计数据可以以 MapReduce 方式计算,并且来自不同分片的值可以在 Elasticsearch 查询的协调节点处进行组合。
此外,通过控制存储桶长度和窗口长度之间的比率,我们传递的每个运行进程的数据具有可预测的内存消耗,这对于系统稳定性很重要。整个过程如下图所示
信标流量的一个关键属性是,它的大部分通信通常具有相似的网络流量字节数。如果我们对单个桶中的所有事件的字节数取平均值,那么不同桶的平均值实际上会更加相似。这只是大数定律在起作用。衡量几个正数(在我们的例子中,这些是平均桶网络流量字节数)相似性的一种好方法是使用一个称为变异系数(COV)的统计量。它捕获值及其平均值之间的平均相对差异。因为这是一个相对值,所以COV越接近 0,表示值越紧密地聚集在其平均值周围。
我们还发现,某些信标中网络流量字节数的偶尔激增会夸大 COV 统计量。为了纠正这个问题,我们在计算 COV 时简单地丢弃了低百分位数和高百分位数的值,这是一种创建稳健统计量的标准技术。我们将此统计量的值阈值设置为明显小于 1,以检测信标的这种特征。
对于周期性,我们观察到当查看桶计数时,信号显示出以下两种特征之一。如果周期小于时间桶长度(即高频信标),则计数在桶与桶之间显示出很小的变化。如果周期大于时间桶长度(即低频信标),则信号具有高自相关性。让我们详细讨论这些。
为了测试高频信标,我们使用一个称为相对方差(RV)的统计量。许多自然现象的速率都可以用泊松分布很好地描述。原因是如果事件以恒定的平均速率随机到达,并且一个事件的发生不会影响其他事件发生的概率,那么它们在固定时间间隔内的计数必须服从泊松分布。
为了强调这一点,事件之间随机延迟的底层机制(例如,泡咖啡、等待软件构建等)并不重要——如果这些属性成立,它们的速率分布总是相同的。因此,我们期望我们网络中的大部分流量的桶计数服从泊松分布,但信标则不然,因为信标更有规律。泊松分布的一个特点是它的方差等于它的平均值,即它的 RV 为 1。粗略地说,这意味着如果我们的桶计数的 RV 更接近 0,则信号比泊松过程更规则。
自相关是一个有用的统计量,用于了解时间序列何时重复自身。自相关的基本思想是将时间序列值与其自身在时间上移动后进行比较。具体来说,它是两组值之间的协方差(当它们更相似时,协方差更大),通过将其除以两组值的方差的平方根进行标准化,这衡量值本身之间的变化程度。
此过程在下面以示意图方式说明。我们将其应用于包含桶计数的时间序列:如果信号是周期性的,则时间桶计数也必须重复自身。从我们的角度来看,自相关的好处在于它能够检测任何周期性模式。例如,事件不需要均匀间隔,但可能像两个事件在时间上彼此靠近发生,然后是长时间的间隔等方式重复发生。
我们事先不知道哪个偏移量会使两组值之间的相似度最大化,因此我们搜索所有偏移量以找到最大值。实际上,这是数据的周期——它的自相关性越接近 1,时间序列就越接近真正的周期性。我们将自相关性阈值设置为接近 1,以测试低频信标。
最后,我们注意到,目前大多数信标恶意软件都包含抖动。自相关如何处理这个问题?首先,自相关不是一个二元度量——它是一个滑动尺度:该值越接近 1,两组值彼此越相似。即使它们不完全相同但相似,它仍然可以接近 1。事实上,我们可以做得更好,通过建模随机抖动如何影响自相关并撤消其影响。只要抖动不太大,执行此操作的过程就与找到最大自相关一样复杂。
在我们的实现中,我们使百分比可配置,尽管人们总是会使用较小的百分比,以避免将太多流量标记为周期性。如果您想深入了解我们实现的详细信息,所有工件都可以在我们检测规则存储库中的 GitHub 版本中找到。
我们如何使用 Elasticsearch 实现这一点?
Elasticsearch 具有一些非常强大的用于临时数据分析的工具。脚本指标聚合就是其中之一。此聚合的优点在于,它允许您编写自定义 Painless 脚本来派生有关数据的不同指标。我们使用聚合来编写信标测试的脚本。
在典型的环境中,跨端点运行的不同进程的基数相当高。因此,尝试运行按每个运行进程分区的聚合是不可行的。这就是 Elastic Stack 的另一个功能派上用场的地方。转换是一种复杂的聚合,它会分页浏览您的所有数据并将结果写入目标索引。
转换中提供了各种基本操作,其中之一是大规模分区数据。在我们的例子中,我们按主机和进程名称对网络事件日志进行分区,并针对每个主机-进程名称对运行我们的脚本指标聚合。该转换还会写出各种与信标相关的指标和统计信息。以下是生成的目的地索引中的一个示例文档
如您所见,该文档包含有关进程的有价值的信标相关信息。首先,beacon_stats.is_beaconing 指示器表示我们是否发现该进程正在信标。如果如上述情况所示,该文档还将包含重要的元数据,例如信标的频率。指示器 beacon_stats.periodic 表示该信号是否为低频信标,而指示器 beacon_stats.low_count_variation 表示该信号是否为高频信标。
此外,指示器 beacon_stats.low_source_bytes_variation 和 low_destination_bytes_variation 表示在信标通信期间发送的源字节和目标字节是否或多或少是统一的。最后,您还会注意到 beaconing_score 指示器,它是 1-3 的值,表示该进程在该时间段内满足的信标测试的数量。
将此类元数据写入索引也意味着您可以在环境中搜索信标软件的不同方面。例如,如果您想在环境中搜索低频信标进程,则可以查询 beacon_stats.periodic 指示器为 true 且 beacon_stats.low_count_variation 为 false 的文档。您还可以在索引数据之上构建二阶分析,例如使用异常检测来查找罕见的信标进程,或者使用显著项聚合来检测环境中信标恶意软件的横向移动。
最后,我们还提供了几个仪表板,供您的威胁猎人和分析师用于监控环境中的信标活动。这些可以在版本包中找到。
调整参数和过滤
高级用户还可以调整转换中脚本指标聚合的重要参数,如抖动百分比、时间窗口等。如果您想更改默认参数,您只需删除转换,更改参数并重新启动即可。您可以调整的参数如下
- number_buckets_in_range:我们将时间窗口划分为的时间桶数。您需要足够的数量来确保您获得各种统计量的合理估计,但太多意味着转换将使用更多的内存和计算。
- time_bucket_length:每个时间桶的长度。这控制时间窗口,因此此值越大,时间窗口越长。如果您想检查非常低频的信标,您可能会将其设置得更长。
- number_destination_ips:要在结果中收集的目标 IP 数量。设置得越高,转换的资源使用量就越大。
- max_beaconing_bytes_cov:对于低源字节和目标字节方差测试,有效负载字节中的最大变异系数。设置得越高,将流量检测为信标的可能性就越大,因此可能会增加恶意 C2 信标的召回率。但是,它也会降低测试的精确率。
- max_beaconing_count_rv:对于高频信标测试,桶计数中的最大相对方差。与 max_beaconing_bytes_cov 一样,我们建议您根据您想要的精确率和召回率之间的权衡来调整此参数。
- truncate_at:计算 max_beaconing_bytes_cov 和 max_beaconing_count_rv 时丢弃的桶值的较低和较高分数。这允许您忽略流量模式的偶尔变化。但是,如果您保留的数据分数太小,这些测试将不可靠。
- min_beaconing_count_autocovariance:对于低频信标测试,信号的最小自相关性。降低此值可能会导致恶意 C2 信标的召回率增加,但代价是降低测试精确率。与上述其他一些参数一样,我们建议您根据您想要的精确率和召回率之间的权衡来调整此参数。
- max_jitter:我们假设周期性信标抖动的最大量,作为其周期的分数。
您还可以更改转换查询。我们目前查找 6 小时时间范围内的信标活动,但您可以将其更改为不同的时间范围。如前所述,信标不是恶意软件特有的特征,许多合法的良性进程也表现出类似信标的活动。
为了抑制误报率,我们在转换查询中包含了一个初始筛选器列表,以排除我们在测试期间观察到的已知良性信标进程,以及一个属于以下两类的 IP 列表
- 源 IP 为本地 IP,目标 IP 为远程 IP
- 对于某些 Microsoft 进程,目标 IP 位于 Microsoft 块中
您可以根据您在环境中看到的情况添加到此列表中。
评估
为了衡量我们的框架作为信标活动缩减搜索空间的有效性,我们想测试两个方面
- 该框架是否标记了实际的恶意信标活动?
- 该框架在多大程度上减少了恶意信标的搜索空间?
为了测试恶意软件信标的性能,我们在一些合成数据以及一些真实的恶意软件上运行了转换!我们设置了 Emotet 和 Koadic 的测试范围,并对几个月前的 NOBELIUM 日志进行了测试。这里值得一提的是真实恶意软件测试的结果。
对于 NOBELIUM,信标转换捕获了违规进程 rundll32.exe,以及两个目标 IP:192.99.221.77 和 83.171.237.173,它们是 NOBELIUM 的主要 IoC 之一。
对于 Koadic 和 Emotet,转换也能够标记进程以及测试 C2 监听器正在运行的已知目标 IP。每个信标的特征都不同。例如,Koadic 是一个直接的、高频率的信标,它满足转换中正在检查的所有信标标准,即周期性以及源和目标字节的低变化。Emotet 稍微棘手一些,因为它是一个低频率、高抖动百分比的信标。但是,由于信标的源字节变化较小,我们能够检测到它。
为了测试搜索空间的减少量,我们在一个内部集群上运行了三周的转换,该集群在测试期间接收来自大约 2000 台主机的网络事件日志。我们根据在运行转换之前和之后,分析师或威胁猎人为识别恶意信标而必须筛选的网络事件日志消息、进程和主机的数量来衡量搜索空间的减少。数字如下:
虽然搜索空间的减少是显而易见的,但另一点值得注意的是,这些转换能够轻松处理的数据规模,这成为一个重要的考虑因素,尤其是在生产环境中。此外,我们还发布了仪表板(可在发布包中找到),用于跟踪信标进程的普及率等指标,这些指标可以帮助做出明智的决策,以便进一步过滤搜索空间。
虽然发布的仪表板和上表中的统计数据是基于 beacon_stats.is_beaconing 指示器为真的情况,即满足任一信标测试的信标,但威胁猎人可能希望通过从最明显的类似信标的情况开始,然后转向不太明显的情况来进一步简化他们的搜索。这可以通过过滤和搜索 beacon_stats.beaconing_score 指示器而不是 beacon_stats.is_beaconing 来完成,其中 3 分表示典型的信标(满足周期性以及数据包字节低变化测试),1 分表示不太明显的信标(仅满足三个测试中的一个)。
作为参考,我们在内部集群上观察到以下情况:
下一步是什么
我们希望您尝试使用我们的信标识别框架,并在我们改进它的过程中向我们提供反馈。如果您在此过程中遇到任何问题,请通过我们的社区 Slack 频道、讨论论坛,甚至我们的开放检测存储库与我们联系。请继续关注本博客的第 2 部分,我们将介绍如何从识别信标活动到实际检测恶意信标!
通过 Elastic Cloud 的 14 天免费试用来试用我们的信标识别框架。