
在2025年初,一家公司部署于香港某数据中心的一批Web应用服务器因在运行过程中记录了包含用户敏感信息的日志,被本地数据合规监管部门发出正式警告函。警告中指出,系统日志中存在未脱敏的身份证号码、手机号码、电子邮箱等字段,严重违反了《香港个人资料(私隐)条例》(PDPO)中的相关数据最小化及访问控制原则。
此次事件虽然未造成数据泄露,但暴露出这家公司在日志管理、敏感信息脱敏与审计记录等方面存在明显短板。为避免类似事件再次发生,并满足日趋严格的合规要求,我们开展了一次全面的问题排查与系统加固工作。本文记录了故障排查与技术整改全过程,供有类似需求的运维、安全与开发团队参考。
问题排查过程
1. 初步分析与日志取证
收到监管警告后,第一时间从以下几个方向入手:
日志来源定位:检查各类系统与应用日志,最终定位到一台Nginx反向代理服务器及三台Tomcat业务服务器输出的日志文件中存在明文敏感字段。
敏感字段确认:通过关键字匹配与正则筛查发现,日志中包含多个格式如:
- 手机号:^1[3-9]\d{9}$
- 身份证号:\d{6}(19|20)?\d{2}(0[1-9]|1[0-2])(0[1-9]|[12][0-9]|3[01])\d{3}[\dXx]
- 邮箱地址:[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}
2. 日志生成机制复盘
进一步检查各类日志配置:
Nginx access_log:
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" $request_body';
问题:Nginx配置中将$request_body完整记录,导致POST请求中包含的身份证、手机号被原样写入日志。
Java 应用日志(Logback):
logger.info("Received login request from: {}", requestBody.toString());
问题:开发阶段便于调试直接输出了原始Request对象内容。
日志聚合系统(ELK Stack): Filebeat → Logstash → Elasticsearch → Kibana,未配置任何字段过滤或脱敏规则。
问题根因总结
- 缺乏统一的日志脱敏标准与规范。
- 未对日志系统中的输入内容做内容分类与敏感字段识别。
- 开发阶段调试日志未在上线前清理或屏蔽。
- 运维日志采集组件未设过滤敏感信息功能。
技术整改方案
1. Nginx 日志脱敏配置
通过Lua脚本动态拦截并处理日志记录内容:
log_by_lua_block {
local body = ngx.var.request_body
if body then
-- 替换手机号
body = string.gsub(body, "1[3-9]%d%d%d%d%d%d%d%d%d", "[REDACTED_PHONE]")
-- 替换身份证号
body = string.gsub(body, "%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d", "[REDACTED_ID]")
end
ngx.var.filtered_body = body or ""
}
log_format custom '$remote_addr [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" "$filtered_body"';
access_log /var/log/nginx/access.log custom;
2. Java 应用层日志过滤
引入脱敏工具类,统一处理日志输出:
public class LogSanitizer {
public static String sanitize(String input) {
if (input == null) return null;
return input
.replaceAll("\\d{17}[\\dXx]", "[REDACTED_ID]")
.replaceAll("1[3-9]\\d{9}", "[REDACTED_PHONE]")
.replaceAll("[\\w._%+-]+@[\\w.-]+", "[REDACTED_EMAIL]");
}
}
使用示例:
logger.info("Processed input: {}", LogSanitizer.sanitize(requestBody.toString()));
3. Logstash 过滤插件增强
在logstash.conf中添加Groovy过滤器:
filter {
grok {
match => { "message" => "%{GREEDYDATA:raw}" }
}
mutate {
gsub => [
"raw", "\d{17}[0-9Xx]", "[REDACTED_ID]",
"raw", "1[3-9]\d{9}", "[REDACTED_PHONE]",
"raw", "[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}", "[REDACTED_EMAIL]"
]
}
}
4. 引入审计与变更追踪机制
为提升可审计性,引入如下措施:
- 操作记录审计:在Elasticsearch中建立审计索引,对敏感操作日志脱敏存储,同时原始记录加密保存,仅特权账号可访问。
- 敏感日志访问追踪:Kibana中设置带条件的监控告警,例如“谁在检索身份证字段内容”,实时发出报警。
- 代码变更审核制度:上线前通过自动代码扫描(如SonarQube),审查是否有未脱敏日志输出。
效果验证与数据支撑
整改完成后,进行了以下验证:

本次事件虽未造成直接的数据泄露事故,但警示我们必须将日志作为隐私数据管理的重要一环,与数据库、缓存系统具有同等级别的保护机制。建议各技术团队:
- 明确制定并推行统一的日志输出规范。
- 在开发阶段即引入脱敏机制,防止调试日志入库。
- 定期对日志系统进行合规自查,结合AI识别与异常审计策略。
- 尽早在架构层面引入敏感信息识别与分级保护框架。
通过本次事件整改,企业建立了更严密的日志防护体系,为后续境内外合规审计与数据安全建设奠定了坚实基础。希望本文能为同行在处理类似问题时提供实践参考。











