4、审计日志字段解析:时间戳提取、源IP/目标IP提取、用户与事件类型识别归纳
字段解析,说白了就是让机器读懂日志。嗯,我刚开始做 Splunk 的时候,拿到原始日志直接搜,结果一堆乱码。后来才明白——字段不解析好,搜索效率、告警准确性全白搭。这一章咱们就把审计日志里最常见的四个核心字段拆开揉碎:时间戳、源 IP、目标 IP、还有用户和事件类型。
4.1 时间戳提取:别让日志"穿越"
时间戳是审计日志的灵魂。我记得有一次排查安全事件,日志时间比实际慢了8小时,差点误判攻击时间。为什么会这样?因为 Splunk 默认用日志到达时间(_indextime),可真正有用的,是日志里那个原始时间。
本质上你要做两件事:告诉 Splunk 时间戳在哪个字段里,以及它的格式是什么。默认 Splunk 自动识别常见格式(比如 ISO 8601),但遇到自研系统或者老设备,你就得上手了。
2025-03-21 14:32:18,452 host=10.0.1.5 action=login user=zhang
在 props.conf 里写:
TIME_PREFIX = ^
TIME_FORMAT = %Y-%m-%d %H:%M:%S,%3N
如果只想在搜索里提取,用:
| eval extracted_time = strptime(raw, "%Y-%m-%d %H:%M:%S,%3N")
| convert ctime(extracted_time)
| 日志来源 | 典型格式 | TIME_FORMAT 示例 |
|---|---|---|
| Linux syslog | Mar 21 14:32:18 | %b %d %H:%M:%S |
| Windows Event Log | 03/21/2025 14:32:18.452 | %m/%d/%Y %H:%M:%S.%3N |
| Nginx access | 21/Mar/2025:14:32:18 +0800 | %d/%b/%Y:%H:%M:%S %z |
| 自研微服务 JSON | "timestamp": 1711003938452 | epoch 毫秒 → 用 eval 转换 |
4.2 源IP/目标IP提取:从混乱到有序
审计日志里 IP 通常是成对出现的:src_ip 和 dest_ip。但不同设备写的字段名千奇百怪——saddr、sourceAddress、clientip、host……你想想看,如果手写正则匹配每次都不一样,那还怎么自动化?
我的做法分两步:先用字段提取把所有可能的名字统一,再用 eval 做标准化。
4.2.1 搜索时用 rex 或 spath
对于非结构化的文本日志,用 rex 正则拿到 IP:
| rex "from (?<src_ip>\d+\.\d+\.\d+\.\d+) to (?<dest_ip>\d+\.\d+\.\d+\.\d+)"
对于 JSON 格式,直接用 spath:
| spath path=source_ip output=src_ip
| spath path=dest_ip output=dest_ip
4.2.2 用 eval 做归一化
因为字段名乱,我喜欢建一个辅助 sourcetype 级别的字段别名表:
| eval src_ip = coalesce(src_ip, sourceAddress, saddr, clientip)
| eval dest_ip = coalesce(dest_ip, destAddress, daddr, server_ip)
这样不管原始字段叫什么,最终都收口到 src_ip 和 dest_ip。
4.3 用户与事件类型识别:谁干了什么
审计日志的两个灵魂拷问:谁干的?干了什么事?用户字段常见的有 user, username, uid, account, identity。事件类型更乱——action, operation, event, result 等等。
我一般先把用户字段归一化,再根据事件类型打标签。举个例子,将不同的登陆成功、失败统一成 "login_success" 和 "login_failure":
| eval user = coalesce(user, username, uid, account)
| eval event_type = case(
action=="LOGIN" AND result=="SUCCESS", "login_success",
action=="LOGIN" AND result=="FAILED", "login_failure",
action=="DELETE" OR action=="remove", "delete_operation",
action=="CREATE" OR action=="add", "create_operation",
1==1, "other"
)
这样不管原始日志写什么,最终都能归纳到可统计的类别里。我在做 UBA(用户行为分析)时,就靠这个 event_type 字段做基线建模,效果立竿见影。
4.4 字段解析全流程梳理
上面几步走下来,其实已经形成了一个完整的提取链路。我把它画成一张图,方便你对照落地。
你按这个流程去配置你的 props.conf 和搜索,再复杂的审计日志都能规整。最后把结构化字段丢进告警里,基本就落地了。
4.5 小总结:字段解析的价值在哪
说白了,字段解析就是给原始日志穿上「制服」。时间戳、IP、用户、事件类型这四个字段一旦统一,后面做统计、关联、异常检测就顺利多了。我有一次要排查服务器被暴力破解的源IP,按上面的方法归一化后,一条 | stats count by src_ip user event_type 就锁定了攻击者。嗯,搞定。下次你遇到类似场景,试试这套流程。