运维笔记

Splunk SIEM 关联规则最佳实践:从踩坑到优雅,资深工程师的硬核指南

Cybersecurity 技术可视化

写在前面:别让默认规则毁了你

先泼一盆冷水。如果你刚部署 Splunk ES,第一件事就是把所有默认关联规则全部关掉。别问为什么,问就是血泪教训。

Reddit 上有个老哥说得特实在:“Splunk ES default correlation searches should not be turned on!” 这不是矫情,是真理。默认规则是为通用场景设计的,而你的环境大概率不是通用场景。直接打开,你的 SIEM 会瞬间变成警报制造机——不是安全告警,是噪音污染。

我去年接手过一个客户,他们开箱即用跑了三个月,每天平均 2000+ 告警,实际有效的不超过 10 个。SOC 团队直接崩溃,最后把所有规则全关了,从零开始重写。这浪费的时间,够写两套完整的规则库了。

所以,先归一化你的数据,再谈规则。这是第一原则。

关联规则的“三明治”结构

写 Splunk 关联规则,说白了就是做三件事:收集数据、结构化信息、输出知识。我管这叫“关联三明治”——最底层是原始日志,中间层是字段提取和标准化,顶层是逻辑判断。

很多人一上来就写 search 命令,结果就是一团乱麻。正确的姿势是这样的:

第一步:数据归一化(别跳过!)

没有归一化,规则就是废的。你得确保不同设备、不同格式的日志能映射到同一个字段体系。

index=firewall OR index=proxy OR index=endpoint
| eval src_ip = coalesce(src_ip, clientip, source_ip, src)
| eval dest_ip = coalesce(dest_ip, dest, destination_ip, dst)
| eval user = coalesce(user, username, account_name, sAMAccountName)

看着简单吧?但 90% 的团队在这一步就翻车了。字段名不统一,后面的逻辑根本跑不通。

第二步:定义威胁模式

这是核心。你要回答一个关键问题:什么场景组合在一起,才构成一个真正的威胁?

举个例子,检测暴力破解:

index=windows EventCode=4625
| bucket _time span=5m
| stats count as failed_attempts by src_ip, TargetUserName
| where failed_attempts > 10

但这就够了吗?不够。单靠这个规则,你可能会把正常的员工误操作也当成攻击。更好的做法是加入上下文:

index=windows EventCode=4625
| bucket _time span=5m
| stats count as failed_attempts by src_ip, TargetUserName
| where failed_attempts > 10
| lookup local=true privileged_accounts TargetUserName OUTPUT privileged
| where isnull(privileged) OR privileged="false"
| eval risk_score = failed_attempts * 10

看到了吗?排除正常用户,再加一个风险评分。这才是生产级的规则。

第三步:阈值设置——别猜,要算

关于阈值,有个经典问题:“What are the two types of thresholds which may be used in correlation searches?”

答案是 count-based(基于计数)time-based(基于时间)

但更重要的不是类型,而是怎么设。我见过太多人拍脑袋设阈值:失败登录 5 次就告警?10 次?100 次?

正确做法:拿你环境的历史数据跑一遍,看分布。

index=windows EventCode=4625
| timechart span=1h count by src_ip usenull=f
| eventstats avg(count) as avg_count, stdev(count) as stdev_count
| eval threshold = avg_count + (3 * stdev_count)
| where count > threshold

用标准差来动态计算阈值,比拍脑袋靠谱一百倍。

最佳实践速查表

实践要点说明我的评分
数据归一化优先先统一字段映射,再写规则逻辑⭐⭐⭐⭐⭐
默认规则全关从零开始,按需启用⭐⭐⭐⭐⭐
使用 lookup 丰富上下文引入资产、用户、威胁情报⭐⭐⭐⭐
动态阈值基于历史数据计算,而非硬编码⭐⭐⭐⭐⭐
规则分级区分严重等级,避免告警疲劳⭐⭐⭐⭐
定期回顾与调优每月至少 review 一次规则命中率⭐⭐⭐⭐⭐
避免过于复杂的规则单个规则不要超过 50 行⭐⭐⭐
利用 risk 命令Splunk ES 内置的威胁评分机制⭐⭐⭐⭐

常见坑(我踩过的)

坑 1:规则太“松”

规则写得太宽泛,结果就是全量告警。比如:

index=* "malware" OR "virus"

这能检出什么?什么都能检出,但什么都不准。正确的做法是缩小数据源范围,只查你确定能产生有效告警的日志源。

坑 2:忽略时间窗口

关联规则的核心是事件序列。如果你不设时间窗口,规则就变成了“只要有 A 和 B 就告警”,完全忽略先后顺序。

index=windows EventCode=4624
| join type=inner src_ip [search index=proxy dest_ip=10.0.0.1 | fields src_ip]

这个 join 会匹配所有时间点的数据,而不是一个合理窗口内的。正确的做法是用 transactionstats 配合时间桶。

坑 3:不处理假阳性

规则上线后,第一周你会收到一堆假阳性。别急着改规则,先建一个排除列表

| search NOT [| inputlookup exclude_ips | fields src_ip]

等排除列表稳定了,再考虑调整规则本身。

FAQ

How to write correlation rules in SIEM?

写规则的核心是三步:归一化数据、定义威胁模式、设置阈值。归一化让不同来源的日志能统一处理;威胁模式定义什么样的事件组合算攻击;阈值决定什么时候触发告警。别跳过任何一步。

How to write correlation rules in Splunk?

Splunk 里写规则,首选 search 命令,配合 statstransactionlookup。记住用 risk 命令给告警打分,而不是直接触发。规则要写在 Splunk ES 的 Correlation Search 界面里,别写在普通搜索里当定时任务跑。

Why do we make correlation rules in SIEM?

因为单一日志事件没有意义。一次失败登录可能是手滑,但 10 次失败登录加一个成功的登录,可能就是暴力破解。关联规则把孤立的事件串起来,还原攻击链。

What are the two types of thresholds which may be used in correlation searches?

基于计数(count-based)和基于时间(time-based)。前者看事件数量是否超过阈值,后者看事件是否在指定时间窗口内发生。生产环境通常两者结合使用。

最后说两句

我写这文章的时候,Hacker News 上正好有个帖子在讨论 “Nano – open core siem built on rust and ClickHouse”。说实话,Rust 和 ClickHouse 的组合在性能上确实有优势,但 SIEM 的核心从来不是技术栈,而是规则的质量和运维的成熟度。

你用一个高性能的 SIEM 跑了一堆烂规则,结果就是更快地产生更多垃圾告警。

所以,别急着追求新玩具。先把基础打好,把规则写好,比什么都强。


以上内容基于过去 30 天 Reddit 和 Hacker News 的社区讨论,以及我个人的实战经验。规则写法因环境而异,请务必在实际部署前充分测试。


✅ All agents reported back! ├─ 🟠 Reddit: 12 threads ├─ 🟡 HN: 1 story │ 3 points └─ 🗣️ Top voices: r/BestofRedditorUpdates, r/Splunk, r/Huntercallofthewild