这类问题我又碰上了一次。日志里把 JWT 按点号切分,只把前两段替换成 ***,第三段签名原样保留,安全评审指出签名可以离线校验并配合已知 payload 反推用户身份。

第一反应是「脱敏只做了一次字符串替换,没覆盖 URL 参数里的 token」,验证下来不成立。

把日志和配置对完,能解释这个现象的基本就这几处。签名段本身可被用于校验猜测的 payload;日志里同时打印了 kid 与签发时间,可缩小枚举范围;网关与业务两侧各打一份日志,只有一侧做了脱敏。

第一件事是确认日志里 token 的完整形态与出现位置

python -c "import re;print(re.findall(r'eyJ[\\w-]+\\.[\\w-]+\\.[\\w-]+','app.log')[:2])"

整段 token 一律替换而不是分段保留

python -c "import re;print(re.sub(r'eyJ[\\w-]+\\.[\\w-]+\\.[\\w-]+','***',open('app.log').read())[:60])"

随后把 URL 查询参数里的 token 一并纳入规则

python mask_log.py --patterns jwt,query_token --apply

回放历史日志检查残留

python replay_mask.py --log old.log --pattern 'eyJ' --report left.txt

改完先别撤,确认这几项。日志里不再出现完整 JWT 的任何一段,URL 参数与请求头两条路径都被覆盖,残留检查为零。

补一句。JWT 三段是一个整体,留任何一段都可能被利用,脱敏规则要按整串匹配,并且覆盖 header、URL、body 三个位置。同一份配置在测试环境跑通,不代表线上没事,两边的默认值经常不一样。

作者 9823189