使用Splunk查找表加速检测工程

本文介绍了如何利用Splunk查找表功能快速实现基于字符串的检测规则,通过将Sigma规则转换为CSV格式的查找表,显著减少检测规则的部署时间,并提供了三种具体的SPL搜索方法及其优缺点分析。

使用Splunk查找表加速检测工程

概述

这篇文章介绍了如何通过Splunk的查找表功能,快速减少基于简单字符串检测的新检测规则实施时间。例如"如果看到dump /service:krbtgt则触发"这样的检测场景。

虽然检测即代码的部署可能会减少对此类方法的需求,但根据我的经验,基于字符串搜索的新规则部署时间通常过长。

背景

新规则开发的常见流程是:阅读报告、识别TTP的独特实现、创建或获取规则(例如从Sigma规则库获取)。即使使用检测即代码,这仍然可能是一个漫长的过程,并且可能导致拥有数百个检测规则,每个规则都有自己的管理开销,而这些规则本质上可能只是字符串指示器。

解决方案 - 使用查找表!

在Splunk中,查找表本质上是一个CSV表格,可以存储我们想要查找的数据。

简化的现有IOC威胁匹配在Splunk中使用查找表/kv存储。我们只是将这个概念扩展到包含字符串片段,如mimikatz,但增加了我们想要查看这些字符串的字段 - 例如命令字段。

Sigma规则示例

以这个查找命令行参数的Sigma规则为例:

Sigma规则示例

所有感兴趣的内容只是出现在CommandLine中的字符串。我们只是想将这样一个简单Sigma规则的主题转换为CSV结构。

对于上面的例子,我们可以看到它查找多个命令行片段中的任何一个。这确实说明了基于查找表方法的一个限制:如果我们不想承担分割分隔字段的开销,那么它们都必须放在单独的行上,这对某些规则来说可能相当"不整洁"。

示例查找文件

下面的示例查找文件存储了我们最感兴趣的信息,例如:

  • l_field = 我们要查找值的字段
  • l_value = 我们要查找的值(注意周围的通配符)
  • l_description/l_name = 名称和描述
  • l_references = 任何有用的调查参考
  • l_severity = 可能触发的严重性(可在RBA计算中用作风险因子)

在Splunk搜索中使用查找表

有几种方法可以在Splunk搜索中使用此查找表,每种方法的效率各不相同。基本思想是能够指向索引,告诉它我们关心哪些字段,然后进行查找。

重要步骤:

  1. 确保为查找表定义了查找定义
  2. 确保在查找定义中将搜索字段启认为通配符字段
  3. 所有搜索项都应保存为带有周围通配符*的形式

示例SPL:方法1 - 首先使用inputlookup子搜索的Tstats

1
2
3
4
5
6
7
8
| tstats summariesonly=true c from datamodel="Endpoint.Processes" 
where `rule_tuning_macro` 
[|inputlookup string_indicator_lookup | rename l_value as Processes.process | fields Processes.process] 
by _time Processes.process Processes.user host
| rename Proceses.* as *
| eval lookup_field="command"
| eval lookup_value=process
| lookup string_indicator_lookup l_field as lookup_field l_value as lookup_value

这里我们使用加速的数据模型,并使用内部搜索(inputlookup),在其中重命名然后仅将字符串输出到我们关心的字段中(此处为processes.process)。

我们可以针对这个较小的数据集进行搜索,并直接使用查找表来丰富任何发现。

与编写规则的良好实践一样,我们包含一个调优宏,其中包含我们的误报等,包括使用原始数据中存在的其他字段进行调优。

缺点: 随着查找文件的增长,由于inputlookup命令在Splunk索引器上的工作方式,这可能会相当慢。搜索需要定期运行并且时间窗口要小。

示例SPL:方法2 - 使用Tstats提取所有数据然后进行查找

1
2
3
4
5
| tstats summariesonly=true c from datamodel="Endpoint.Processes" where `rule_tuning_macro` by _time Processes.process Processes.user host
| rename Proceses.* as *
| eval lookup_field="command"
| eval lookup_value=process
| lookup string_indicator_lookup l_field as lookup_field l_value as lookup_value

在这个例子中,我们查看加速端点数据模型中的所有命令(Processes.process),然后对每个命令进行查找,允许我们查看查找表中的所有字段,如描述或参考。同样,我们使用调优宏。

缺点: 这可能相当慢,因为它首先将所有命令拉入内存,所以在短时间内运行它,尽管查找文件增长的影响可能较小。

示例SPL:方法3 - 在非数据模型数据上,使用inputlookup AND lookup

1
2
3
4
5
6
{{YOUR DATA}}
| eval lookup_field="command"
| eval lookup_value=command
| search
[|inputlookup string_indicator_lookup | eval search=l_value |fields search | format ]
| lookup string_indicator_lookup l_field as lookup_field l_value as lookup_value

这里我们不使用加速的数据模型,但为了加速,我们使用2次传递。

第一次inputlookup在原始数据中查找我们关心的字符串 - 此时它可能出现在任何字段中,但这应该会大大减少后续查找的数据集。

我们随后进行一个查找,确保匹配发生在正确的字段上,并用查找表中的上下文丰富它。

进一步探索

这些搜索相当基础,所以我想探索一些想法:

  • 使用分隔符减少重复/多行 - 我认为涉及的解析可能会严重影响搜索时间,特别是因为我们不能进行简单的查找。但我想进一步研究这一点。
  • 附加字段,如parent_process - 仅当两者都满足时
  • 在查找表中添加逻辑 - 在查找表中存储Sigma逻辑并在SPL搜索中使用,如’ANY’、‘ALL’
  • 在摄取/实时执行 - 我希望在原始日志进入Splunk时进行简单的模式匹配,有点像IDS。我想看看在摄取时进行这样的查找有多可行。

结论

诚然,可能有一个点,在查找表中执行这些操作比拥有多个规则效率更低。然而,目标是在阅读报告时,从"嘿,我们可能可以查找那个"到实际有一个规则在查找它,大大减少复杂性和所需时间。

如果有人有任何反馈,请告诉我!(我确实喜欢重新发明完美的轮子,所以如果有更好的方法,请告诉我!)

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计