2. 日志存储与格式
聊到日志篡改和注入攻击,先得把底层的“食材”搞明白——日志到底长什么样,存在哪儿。我刚开始做安全运维那会儿,接过一个客户现场:告警系统天天报“日志格式异常”,查了半天才发现,他们同一台服务器上混着三种不同的日志格式,解析器直接崩溃了。嗯,从那以后我养成了一个习惯——先统一格式,再谈分析。
说白了,日志格式决定了你能做什么。是结构化还是半结构化,字段固定还是自由文本,这些会直接影响你后面的检测算法能不能跑得动。这一节我们就把主流的几种格式和存储策略捋一遍。
2.1 常见日志格式一览
目前生产环境中碰得最多的就三种:Syslog、JSON、CSV。还有少数用 XML、Protobuf 的,但那是大厂的定制玩法,咱们先放一放。下面这张表能帮你快速看清它们的差异:
| 格式 | 结构化程度 | 可读性 | 机器解析效率 | 常见场景 |
|---|---|---|---|---|
| Syslog | 半结构化 | 高 | 中等 | 网络设备、Linux 系统日志 |
| JSON | 全结构化 | 中等 | 高 | Web 应用、微服务、API 网关 |
| CSV | 结构化(平表) | 高 | 高 | 历史分析、批量导入 |
2.2 Syslog——老将依然能打
Syslog 是日志界的老大哥了。RFC 3164 定义了传统格式,后来 RFC 5424 做了结构化扩充。你想想看,一台路由器每天能喷几十万条 syslog,格式不规范的话根本没法处理。
传统 Syslog 长这样:
<34>Oct 11 22:14:15 mymachine su: 'su root' failed for lonvick on /dev/pts/8
前面的数字 <34> 打包了 facility 和 severity。我记得有一次线上事故,防火墙的日志等级被人误配成了 DEBUG,结果一天刷了 200GB 的 syslog,直接把集中存储撑爆了。所以这里的 facility 和 severity 很重要——我建议在接收端就做过滤,不要把垃圾全吃掉。
RFC 5424 引入了结构化数据字段:
<165>1 2003-10-11T22:14:15.003Z mymachine.example.com su - - [exampleSDID@32473 iut="3" eventSource="Application" eventID="1011"] BOM'su root' failed for lonvick on /dev/pts/8
这个版本多了时间戳(带时区)、hostname、app-name、结构化数据。好处是提取字段方便了,坏处是——很多老旧设备根本不支持,你得到处适配。
RSyslog 的 RELP 协议或者直接走 TCP/TLS。
2.3 JSON——现代日志的默认选择
JSON 日志现在基本是 Web 应用的标配。每个请求一条 JSON,字段包括 timestamp、level、caller、message,还有业务上下文。一个典型的 JSON 日志行:
{
"timestamp": "2025-04-11T14:23:00.123Z",
"level": "ERROR",
"logger": "com.example.payment.Service",
"thread": "http-nio-8080-exec-5",
"message": "Payment timeout for order #12345",
"extra": {
"orderId": "12345",
"amount": 299.99,
"retryCount": 3
}
}
为什么要强调 JSON?因为处理攻击日志时,字段名就是检测规则的锚点。比如我检测 SQL 注入,直接看 request.body 或者 queryString 字段,正则匹配效率高得多。CSV 想做同样的事,你还得记列号,非常容易搞混。
不过 JSON 也有坑:日志量大的时候,序列化和反序列化开销不小。我经历过一个系统,每条 JSON 日志里都嵌了完整堆栈,结果一天日志 500GB,ES 集群直接写崩了。后来我们规定:错误日志才保留堆栈,INFO 级别只留 message。
2.4 CSV——轻量但容易篡改
CSV 简单,也真的很脆弱。我见过有人直接用 Excel 打开 CSV 日志,保存后引号、逗号全变了,整个结构就毁了。而且 CSV 没有转义标准,如果日志内容里带逗号或换行,解析器很容易栽。
一个规范 CSV 日志示例:
timestamp,level,source,message
2025-04-11 14:23:00,ERROR,payment,"Payment timeout for order #12345"
2025-04-11 14:25:12,WARN,gateway,"Rate limit exceeded for IP: 10.0.0.1"
CSV 的最大问题是“字段顺序依赖”——如果你加了一个新字段,所有下游解析脚本都要改。而且字段没有自描述性,你拿到一个 CSV 文件,不知道第 3 列是什么。说难听点,攻击者要伪造 CSV 日志成本极低,因为缺乏结构校验。
所以我的建议是:CSV 只用于导出和分析,别当主存储格式。
2.5 日志存储策略
格式定好了,接下来就是怎么存。我见过最糟的案例:某公司把所有日志都打到同一个文件里,不轮转,不压缩,结果一个日志文件 200GB,vim 都打不开。存储策略一般从这几个维度考虑:
- 存储位置: 本地磁盘、NFS、集中式日志系统(ELK、Graylog、Splunk)、对象存储(S3、OSS)
- 保留周期: 按合规要求(我是金融行业客户一般保留 180 天~1 年),热数据 7 天、温数据 30 天、冷数据归档
- 轮转策略: 按大小(如 500MB)或按时间(每天/每小时)切分,配合压缩(gzip)
- 写一致性: 使用 append-only 模式,避免随机写损坏
下表是我总结的几种存储方式适用场景:
| 存储方式 | 延迟 | 吞吐 | 防篡改性 | 推荐场景 |
|---|---|---|---|---|
| 本地文件(ext4/XFS) | 低 | 高 | 低(易被本地修改) | 临时调试、边缘节点 |
| 集中式日志系统 | 中 | 中 | 高(可审计、只读) | 生产环境、安全分析 |
| 对象存储(写一次读多次) | 高 | 低~中 | 极高(不可变对象) | 归档、合规保留 |
/var/log/buffer/),再异步上传到集中存储。这样既保证写入速度,又避免网络抖动丢日志。
2.6 安全视角下的格式与存储
日志篡改检测的核心之一,就是“能不能发现日志被改了”。如果日志是 CSV 纯文本,攻击者可以直接改文件内容,你很难追踪。如果日志是 JSON 带签名(比如每条日志末尾加 SHA256 值),或者存储在 WORM(Write Once Read Many)存储里,那篡改的成本就高很多。
我个人实践中,推荐 JSON 格式 + 集中存储 + 哈希链(Hash Chain)的方案。每条日志包含前一条的哈希,形成链式验证。这我们在后面第 5 章会详细讲。
/var/log 设成 777,攻击者直接追加恶意日志。我建议生产环境日志目录权限设为 755 或 750,日志文件 640,并配置 logrotate 后自动压缩加密。
下面这张图能帮你把格式和存储策略串起来看:
你看,从源头到格式再到存储,每个环节都有安全取舍。选 JSON 配合集中式日志系统,是目前最容易实现篡改检测的组合。当然,如果业务系统太老旧不能改格式,也可以通过日志采集层(如 Filebeat、Fluentd)做格式转换——但这又会引入“采集点是否可信”的问题,我们后面章节再聊。
- 新系统一律 JSON 格式,字段用
snake_case统一命名 - Syslog 只保留网络设备原始日志,接收后立即转成 JSON
- CSV 只用于导出报表,不做实时分析
- 存储策略按 7-30-180 天分层,对象存储做写后不可变
- 日志目录权限收紧,配置 logrotate 后置压缩加密