4. Splunk搜索处理语言(SPL)基础

SPL(Search Processing Language)是 Splunk 中用于检索、转换、关联和呈现机器数据的核心语言。它的基本形态是一条以管道符 | 串联的命令链:最左侧通常是搜索命令,负责从索引中筛选原始事件;右侧的统计、字段提取、计算、排序等命令则对左侧结果逐级加工。理解 SPL 的关键,不是记住所有命令,而是理解“事件流如何被逐步收敛为可判断的安全结论”。

本节围绕安全事件调查中最常用的六类命令展开:search、stats、eval、rex、table、sort,并给出可直接套用的搜索模式。

一、search:先缩小范围,再谈分析

search 是隐式命令,通常写在管道最左侧。它的职责是从索引中拉取与条件匹配的事件。安全调查中,最忌讳一上来就 index=* 全量扫描,正确做法是用“索引 + 主机/用户/进程 + 时间窗 + 关键字段”四要素快速收敛。

index=win_security EventCode=4625
| search user!="ANONYMOUS LOGON"
| stats count by src_ip, user
| sort - count

这里 EventCode=4625 表示 Windows 登录失败,search user!="ANONYMOUS LOGON" 用于排除匿名登录噪声。注意:search 命令中的字段过滤发生在检索阶段,能显著减少后续命令处理的数据量,因此应尽量把过滤条件前置。

二、stats:把事件变成可判断的统计量

stats 是安全分析中使用频率最高的命令。它按指定字段分组,并计算 count、dc(去重计数)、sum、avg、values 等聚合值。安全场景中,dc 尤其重要,例如统计同一源 IP 尝试登录的不同账号数,可快速识别暴力破解或撞库行为。

index=win_security EventCode=4625
| stats count as fail_cnt, dc(user) as user_cnt,
        values(user) as users by src_ip
| where fail_cnt > 20 AND user_cnt > 5
| sort - fail_cnt

该搜索输出每个源 IP 的失败次数、涉及账号数及账号列表,并用 where 过滤出“失败次数大于 20 且账号数大于 5”的可疑源。这是典型的“聚合 + 阈值判断”模式。

三、eval:生成新字段与判断逻辑

eval 用于创建或覆盖字段,支持算术、字符串、条件判断和时间函数。安全调查中常用它做风险打分、字段拼接和状态标记。

index=win_security EventCode=4625
| stats count as fail_cnt, dc(user) as user_cnt by src_ip
| eval risk = case(
    fail_cnt > 100 AND user_cnt > 10, "high",
    fail_cnt > 20  AND user_cnt > 5,  "medium",
    true(), "low")
| table src_ip, fail_cnt, user_cnt, risk
| sort - fail_cnt

case() 按顺序匹配条件,true() 作为兜底分支。这样就把原始失败事件转化为带风险等级的判断结果,便于后续告警或人工复核。

四、rex:从非结构化文本中提取字段

很多安全日志的关键信息藏在原始文本里,例如防火墙日志中的 URL、命令行参数、注册表路径。rex 通过正则表达式提取字段,语法为 rex field=源字段 "正则(?<新字段>...)"。

index=proxy
| rex field=_raw "Host:\s+(?<host>[^\s]+)"
| rex field=_raw "URI:\s+(?<uri>[^\s]+)"
| stats count by host, uri
| sort - count

提取后即可像普通字段一样参与 stats、where 和 table。需要注意:正则要尽量锚定上下文,避免误匹配;提取字段名不要与已有字段冲突。

五、table 与 sort:让结果可读、可排序

table 只保留指定字段并按列展示,适合生成调查视图;sort 按字段排序,- 表示降序。二者常配合使用,把统计结果整理成“一眼能看懂”的表格。

index=win_security EventCode=4625
| stats count as fail_cnt, dc(user) as user_cnt by src_ip
| eval risk = if(fail_cnt > 50, "high", "normal")
| table src_ip, fail_cnt, user_cnt, risk
| sort - fail_cnt

六、安全事件调查中的常用搜索模式

把上述命令组合起来,可形成几类高频调查模式:

  • 暴力破解识别:EventCode=4625 | stats count, dc(user) by src_ip | where count>20
  • 账号异常登录:统计同一用户在不同 src_ip 的登录次数,用 dc(src_ip) 判断是否异地。
  • 进程链排查:对 EventCode=4688 用 rex 提取命令行,再用 table 展示父进程与子进程。
  • 横向移动线索:统计 EventCode=4624 中 Logon_Type=3 的源 IP 与目标主机组合。

下面这张图概括了 SPL 从原始事件到安全结论的处理链,以及各命令在链中的位置与作用。

SPL 安全事件调查处理链 原始事件 index / sourcetype _time / _raw search 过滤 EventCode / user src_ip / 时间窗 rex 提取 正则捕获字段 uri / cmdline stats 聚合 count / dc / values by src_ip, user eval 判断 case / if 风险分级 risk = high / medium table + sort 字段列视图 按 fail_cnt 降序 安全结论 可疑源 IP / 账号 告警 / 人工复核 常用模式: 暴力破解 → EventCode=4625 | stats count, dc(user) by src_ip | where count>20 横向移动 → EventCode=4624 Logon_Type=3 | stats dc(dest) by src_ip

七、编写 SPL 时的实用建议

第一,过滤前置。把 index、sourcetype、EventCode 等条件写在最左侧,减少后续命令处理量。第二,先聚合再判断。用 stats 把海量事件压缩成少量统计行,再用 where 或 eval 做阈值判断,比逐条查看事件高效得多。第三,字段提取要克制。rex 正则应尽量精确,避免在大数据量上做复杂回溯。第四,结果要可读。table 控制列,sort 控制顺序,让调查结论一目了然。

建议在 Splunk 的 Search & Reporting 应用中,把本节示例逐条执行,观察 stats 前后事件数量的变化,以及 eval 新增字段的效果。理解“事件流如何被收敛”,比记住命令语法更重要。