服务器日志怎样脱敏?保留排障线索又避免泄漏凭据
排障时把所有请求头、参数和响应内容都打印出来,看起来信息最完整,却可能让日志变成第二份敏感数据库。更合理的做法是先明确要回答的问题,再采集必要字段。日志的读者、存放位置和保留时间,应与生产数据一样受到管理。
先为一个具体故障定义需要的字段
假设要判断支付回调为什么失败,通常需要时间、请求关联标识、接口路径、结果状态和错误类型;完整令牌、银行卡资料或会话 Cookie 并不应因此进入普通日志。先选最少可用字段,缺少线索时再有范围、有时限地增加采集。
OWASP 日志指南列举了通常应排除或处理的敏感数据。应用日志也要考虑异常堆栈中的连接字符串、上游返回内容和用户输入,不能只给一个名为 password 的字段做替换,就认为已经全面脱敏。
访问地址也可能带有秘密
有些系统把下载签名、重置令牌或临时身份放在查询参数中。如果代理记录完整请求行,这些值可能随网址一起进入日志。应优先避免在 URL 中承载长期秘密,并按排障需求决定是否记录查询参数。
下面是 Nginx 的一个简化 JSON 日志示例,放在 http 上下文;在对应站点配置中引用该格式。它使用不含查询参数的 $uri,但路径本身仍可能带敏感标识,因此必须根据自己的路由设计再审核字段。
log_format safe_json escape=json
'{"time":"$time_iso8601","method":"$request_method",'
'"uri":"$uri","status":$status,"duration":$request_time}';
access_log /var/log/nginx/site-safe.log safe_json;
新增这条 access_log 不会自动替换同级已有的日志指令;如果原有 combined 日志仍启用,查询令牌仍可能写入旧文件。应核查并调整既有 access_log、配置继承及各 location 的覆盖设置,再用测试令牌检查所有实际日志输出,包括集中采集结果,而不只检查新文件。
Nginx 日志模块文档解释了格式和转义选项。escape=json用于正确转义相应字符,不是自动识别并删除秘密的脱敏器。修改前保留旧配置,语法检查通过后再重新加载,核对日志是否仍可被采集程序正常解析。
应用层采用明确的允许字段
对结构化请求,优先定义可记录的字段,而不是事后从任意对象中猜测哪些内容敏感。嵌套对象、数组、不同大小写和第三方错误对象都可能绕过简单替换规则。认证失败可以记录失败类别和内部请求编号,通常不需要保存用户输入的密码。
需要关联同一次请求时,可以生成不带秘密的请求标识,并让代理、应用和队列记录它。不要直接把访问令牌当作关联键。脱敏后的日志还要保持足够区分度,避免所有错误都只剩一句“失败”,让维护人员再次开启无限制调试来寻找线索。
共享之前做第二次检查
向客服或协作方提供日志时,截取必要的时间范围和相关请求,检查网址、路径、请求头、数据库连接信息和用户数据。使用受控传输渠道,并明确接收者。原始日志可以留在受限存储中,分享副本做脱敏,不必为了发出几行错误而发送整天的访问记录。
如果已经发生日志凭据泄漏,应按凭据可能暴露处理,包括撤销或轮换与使用记录检查;清空当前日志不能让已被复制的凭据自动失效。原始证据的保留与清理应按事件处理安排,避免只删日志却没有解决访问权限问题。
用样本验证规则和日志生命周期
在测试环境构造带测试令牌、嵌套字段和特殊字符的请求,确认日志不出现原值,同时错误定位仍然有效。生产临时调试应有结束时间与负责人,完成后检查额外采集是否关闭。
最后确认日志轮转、归档、访问权限和删除周期能够覆盖所有副本,包括集中平台与备份。保留时间要结合业务、合同及适用要求确定,本文不提供通用法定期限。一个合格的脱敏方案,应既能回答具体故障,也能说明为什么需要保存这些字段、谁可以读取,以及何时不再保留。