头部作为袋子
HTTP日志框架将请求头作为一组键值对的袋子对待。logging API暴露了整个袋子。操作员为调试启用了头部日志记录:当一个请求失败时,头部告诉了故事。没有内置拒绝列表。文档中没有凭据过滤器。全头部到磁盘。
典型请求中的凭据头部:
- Authorization: Bearer eyJhbGciOiJIUzI1NiJ9... (JWT或OAuth令牌)
- Cookie: session=abc123; auth=xyz789
- X-API-Key: sk-live-abc123...
- X-Auth-Token: ghp_abc123... (GitHub个人访问令牌模式)
这些值验证请求。写入日志文件,它们验证任何请求。
凭据管道
一个凭据写入日志文件后,不会停留在一个地方。它会在以下位置旅行:
1. Web服务器将其写入 /var/log/nginx/access.log
2. 日志轮替代理(logrotate)将其复制到 /var/log/nginx/access.log.1
3. 日志船员(Fluentd、Filebeat、Logstash)读取并将其发送到汇聚器
4. 日志汇聚器(Elasticsearch、Splunk、Datadog)索引和存储
5. 根据默认策略,保留30-90天
凭据在这五个位置上同时存在。撤销会话令牌不会从日志汇聚器中删除凭据。它将在整个保留窗口内保持可搜索、可导出和可访问,任何人都可以访问日志。
暴露窗口
内存中的凭据暴露窗口: max(会话持续时间,进程生命周期)。会话:小时到天。进程:小时到周。
日志中的凭据暴露窗口: max(会话持续时间,日志保留时间)。会话:小时到天。保留:30-90天。
从内存中盗取凭据,攻击者必须在会话窗口期间 presente。从日志中盗取凭据只需要访问日志汇聚器,它可以回溯性地获得整个保留期。
MOAD-0003 vs MOAD-0004
MOAD-0003(泄露上下文):凭据在内存中泄露给错误的请求处理器。只有在进程窗口期间,通过线程池访问。短暂的。
MOAD-0004 (Logged Secret): 在磁盘上 persist 的凭据会在 log rotation, log shipping 和 log aggregation 中保持。通过 30-90 天的回溯访问,对任何具有 log 访问权限的人可访问。持久。
结构上的区别: ephemeral vs persistent。修复操作在不同层次进行。
ephemeral vs Persistent
ephemeral/persistent 的区别决定了风险面、修复层次和事件响应要求。
在序列化层面上的凭据 denylist
修复方案:在序列化层面上实现凭据 denylist。在任何头值到达日志输出之前,检查头名称是否在 denylist 中。将值替换为 [REDACTED]。
CREDENTIAL_HEADERS = {
'authorization',
'cookie',
'x-api-key',
'x-auth-token',
'x-csrf-token',
'proxy-authorization',
}
def sanitize_headers(headers: dict) -> dict:
return {
k: '[REDACTED]' if k.lower() in CREDENTIAL_HEADERS else v
for k, v in headers.items()
}
denylist 应位于序列化层,而不是日志查询层。日志查询屏蔽:在凭据到达磁盘后才生效;原始值仍存在,但隐藏在显示中。序列化层屏蔽:凭据从未到达磁盘。原始值永远不会进入日志文件、日志收集器或日志汇聚器。
测试 denylist
三个测试模式:
- 正确:带有 Authorization: Bearer token123 的请求会产生一个日志条目,内容为 Authorization: [REDACTED]
- 错误:带有 Content-Type: application/json 的请求会产生一个日志条目,值保持原样
- 不区分大小写: AUTHORIZATION: Bearer token123 也会产生 [REDACTED] (HTTP 头名称不区分大小写)
denylist 需要维护:需要显式添加新凭据头模式(例如,自定义 X-Service-Auth 头)才能修复。该修复是结构性的,但不是自我维护的。
应用 denylist
一组团队配置了他们的 Nginx �ccess 日志格式,以包含所有请求头来调试生产问题。配置如下:
log_format debug_format '$remote_addr - $request - $http_authorization - $http_cookie';
access_log /var/log/nginx/debug.log debug_format;
他们解决了问题,打算移除调试配置,但更改未能在生产环境中生效,直到下一个部署周期(7 天后)才生效。