3. JWT 常见漏洞:alg=none 攻击、弱密钥爆破、kid 注入、jku/jwk 头部篡改

在压测场景中,JWT 的安全漏洞往往是性能瓶颈之外的“隐形杀手”。攻击者利用 JWT 标准实现中的缺陷,可以绕过认证、伪造身份,甚至直接接管系统。本章深入剖析四种最危险的 JWT 漏洞,帮助你在压测诊断中快速定位安全风险。

3.1 漏洞全景与攻击链路

JWT 漏洞的核心在于 服务端对令牌的信任假设 与 实际校验逻辑 之间的差距。攻击者通常通过篡改 JWT 头部、爆破密钥或注入恶意数据来实施攻击。下图展示了四种漏洞的攻击入口与影响范围:

JWT 常见漏洞攻击链路总览 JWT 令牌 alg=none 攻击 头部 alg: none 弱密钥爆破 HS256 弱密码 kid 注入 SQL/命令注入 jku/jwk 篡改 伪造公钥 攻击结果:绕过认证 → 身份伪造 → 权限提升 → 数据泄露 压测关注点:校验逻辑耗时、异常处理路径、密钥强度

3.2 alg=none 攻击

漏洞原理:JWT 标准允许头部 alg 字段值为 none,表示不使用签名。如果服务端校验逻辑未强制要求签名算法,攻击者可将 alg 改为 none 并移除签名部分,直接伪造任意 payload。

压测诊断要点: 在压测脚本中构造 alg: none 的 JWT 请求,观察服务端是否返回 200 而非 401。如果通过,说明存在严重安全缺陷。

攻击示例:

// 原始 JWT
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

// 篡改后 JWT(alg=none,移除签名)
eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkF0dGFja2VyIiwiaWF0IjoxNTE2MjM5MDIyfQ.
检测方法 预期结果 压测影响
发送 alg=none 的 JWT 服务端应返回 401 Unauthorized 若返回 200,压测结果完全不可信
发送空签名 JWT 服务端应拒绝并记录告警 可能触发异常处理路径,影响性能基线

3.3 弱密钥爆破

漏洞原理:使用 HS256(HMAC-SHA256)对称签名时,如果密钥强度不足(如 secret、123456),攻击者可通过离线字典爆破还原密钥,进而伪造任意令牌。

压测建议: 在压测环境中使用 hashcat 或 jwt_tool 对已知 JWT 进行密钥爆破测试。若能在 1 分钟内破解,说明密钥强度严重不足。

常见弱密钥示例:

  • secret、key、password
  • 123456、qwerty、admin
  • jwt_secret、my_secret_key
  • 长度小于 32 字符的随机字符串

密钥强度对比:

密钥类型 示例 爆破难度 压测风险等级
弱密钥 secret123 秒级破解 极高
中等密钥 MyApp!2024#Secret 小时级破解 高
强密钥 32 字节随机 Base64 不可行 低

3.4 kid 注入攻击

漏洞原理:JWT 头部中的 kid(Key ID)用于指定密钥标识。如果服务端将 kid 直接拼接到文件路径或 SQL 查询中,攻击者可注入特殊字符实现路径遍历或 SQL 注入。

攻击向量分类:

  • 路径遍历注入: kid: ../../etc/passwd 或 kid: /dev/null
  • SQL 注入: kid: ' OR '1'='1
  • 命令注入: kid: ; cat /etc/shadow
压测诊断方法: 在压测脚本中构造包含特殊字符的 kid 值,观察服务端响应状态码、响应体错误信息以及响应时间。若出现 500 错误或异常延迟,说明存在注入风险。

安全实现对比:

实现方式 代码示例 安全性
直接拼接 fs.readFile('/keys/' + kid) 危险
白名单校验 if (!allowedKids.includes(kid)) reject() 安全
UUID 格式校验 /^[a-f0-9-]{36}$/.test(kid) 安全

3.5 jku/jwk 头部篡改

漏洞原理:JWT 支持通过 jku(JWK Set URL)或 jwk(JSON Web Key)头部动态指定公钥。如果服务端未验证 jku 的 URL 来源或直接信任 jwk 中的公钥,攻击者可提供自己控制的公钥,从而用对应的私钥签名任意令牌。

攻击流程:

  1. 攻击者生成自己的 RSA 密钥对
  2. 构造 JWT 头部,将 jwk 设置为自己的公钥
  3. 使用自己的私钥对 payload 签名
  4. 服务端使用 jwk 中的公钥验签,验证通过
压测诊断要点: 在压测请求中插入自定义 jwk 字段,使用自签名私钥生成 JWT。如果服务端接受该令牌,说明存在严重信任缺陷。

jku 安全校验清单:

校验项 说明 压测验证方法
URL 白名单 只允许从可信域名获取 JWK 构造外部 URL 观察是否被拒绝
HTTPS 强制 禁止使用 HTTP 协议 使用 http:// 链接测试
缓存策略 对 JWK 进行缓存并设置 TTL 压测中观察重复请求的耗时变化
公钥指纹校验 验证 JWK 的 thumbprint 篡改公钥后发送请求

3.6 压测场景中的漏洞诊断清单

在压测执行前,建议将以下诊断项纳入测试用例:

漏洞类型 诊断用例 预期安全行为 压测关注指标
alg=none 发送 alg:none 且无签名的 JWT 返回 401 响应时间、错误率
弱密钥爆破 使用常见弱密钥字典离线爆破 无法在合理时间内破解 密钥长度、签名算法
kid 注入 发送 kid 含路径遍历字符 返回 400 或 401 异常响应比例
jku/jwk 篡改 发送自签名 jwk 令牌 返回 401 验签耗时、CPU 使用率
最佳实践: 在压测脚本中集成 JWT 安全检测模块,每次压测前自动执行一轮漏洞扫描。这不仅能发现安全问题,还能确保压测数据不被伪造令牌污染。