3.5 审计与取证
一句话
审计要能回答 “谁、在什么时候、对什么、做了什么、结果如何”,且日志不可篡改;取证是 “把这五要素变成可呈交的证据链”——没有时间源、完整性与访问记录,日志只是一堆文本。
审计日志的五个要素
| 要素 | 内容 | 常见缺失 |
|---|---|---|
| Who | 主体(账号、IP、设备、服务身份) | 只记 IP,不记账号/租户 |
| When | 时间(统一时间源、时区) | 各服务时钟不同、时区混乱 |
| What | 对象(资源 ID、字段变更前后) | 只记 “更新了” 不记改了什么 |
| Action | 操作(读/写/删/导出/授权) | 不区分 “查看” 与 “导出” |
| Result | 成功/失败/拒绝原因 | 只记成功,失败尝试丢失 |
保留期与不可篡改
| 项 | 常见要求 | 实现 |
|---|---|---|
| 留存期 | 等保常要求 ≥6 个月;行业有更长要求 | 分层存储(热 30 天 / 冷 6 个月+) |
| 不可篡改 | 只追加、可验证 | WORM 存储、对象锁、哈希链 |
| 访问控制 | 只有审计员可读,运维不可删 | 独立账号 + 最小权限 + 操作审计 |
| 完整性 | 能证明 “未被改过” | 每条日志带前一条哈希(哈希链) |
代码:带哈希链的审计事件
// 每条审计事件把“上一条的哈希”串进来,篡改一条就会断链
type AuditEvent struct {
Seq uint64 `json:"seq"`
Time time.Time `json:"time"` // 统一 NTP/PTP 时间源
Actor string `json:"actor"` // 账号/服务身份
Tenant string `json:"tenant"`
Action string `json:"action"` // read/export/delete/grant
Resource string `json:"resource"`
Before string `json:"before,omitempty"`
After string `json:"after,omitempty"`
Result string `json:"result"`
PrevHash string `json:"prev_hash"`
Hash string `json:"hash"` // sha256(前 12 个字段 + PrevHash)
}
# 验证日志链是否连续(简化:逐条比对 prev_hash)
jq -r '[.seq,.prev_hash,.hash]|@tsv' audit.ndjson | \
awk 'NR>1 && $2!=prev {print "断链 at seq",$1} {prev=$3}'
反模式
| 反模式 | 后果 |
|---|---|
| 审计日志与业务日志混在一起 | 被轮转清掉、被业务查询淹没 |
| 运维账号能删审计日志 | 内部人可抹痕迹,审计失效 |
| 只记 “成功”,不记失败/拒绝 | 无法发现暴力破解、越权尝试 |
| 不记 “导出了什么” | 大规模泄露无法定位范围 |
| 时间源不统一 | 跨服务无法还原事件顺序 |
| 留存期不足 | 事后调查时日志已过期 |
三条铁律
🔑 审计日志要独立存储、只追加、不可删。
🔑 失败与拒绝同样要记;攻击往往藏在失败里。
🔑 时间源统一;否则 “谁先谁后” 说不清。
自检
Q1 为什么审计日志不能和业务日志放一起?
▸ 答案:因为业务日志会按容量轮转/采样/被业务方清理,审计日志需要 “完整、长期、不可删”。混在一起通常导致 “出事时关键记录已被轮转掉”。审计要独立通道、独立存储、独立权限。
Q2 为什么 “失败的操作” 也要审计?
▸ 答案:因为攻击与内部风险常表现为大量失败:暴力破解、越权尝试、扫描、误配置。只记成功会漏掉这些信号;失败日志还能证明 “系统确实拒绝了”,在取证时同样重要。
Q3 哈希链能防什么、不能防什么?
▸ 答案:能防事后篡改(改一条就断链,可被发现);不能防 “从一开始就不记”(漏记无法通过哈希发现)。所以还需要 “记录完整性监控”(如关键操作必须产生审计事件,缺失即告警)。
Q4 时间源为什么是取证的关键?
▸ 答案:因为取证要还原 “事件顺序”:谁先登录、谁先导出、谁后删除。各服务时钟漂移会让顺序颠倒,甚至出现 “删除早于创建” 的荒谬结论。统一 NTP/PTP 并记录时区,是取证可信的前提(见 23.1 物理时钟与漂移)。
Q5 取证时 “证据链” 指什么?
▸ 答案:指 证据的获取、传输、存储、访问都有记录且可验证:谁在什么时候导出了什么、哈希是多少、存到哪里、谁看过。缺任一环,证据的 “未被篡改” 就无法证明,可能在调查/诉讼中不被采信。
Q6 审计日志里能不能放明文个人信息?
▸ 答案:尽量不放:审计需要的是 “谁对哪个资源做了什么”,通常用资源 ID + 字段名即可,不必记录字段值。确需记录值时(如金额变更),要做脱敏/加密与访问控制,避免审计系统变成最大的泄露源。
Q7 怎么验证 “审计真的可用”?
▸ 答案:做一次演练:给定一个场景(如 “某账号导出了 10 万条用户数据”),要求团队在限定时间内回答 “谁、何时、导出了哪些、是否成功、日志是否完整”。答不出来,说明审计只是 “有日志”,不是 “可取证”。
关联
- 前置:3.1 等级保护与网络安全法、3.2 个人信息保护与 GDPR
- 并列:3.3 数据出境与数据主权、50.2 日志 (结构化 / 采样 / 成本)
- 下游:38.11 安全应急响应、23.1 物理时钟与漂移