文章总结: 本文系统梳理JWT常见攻击面与防御要点,包括alg=none绕过、算法混淆(RS256转HS256)、弱密钥字典爆破、kid注入、claims伪造及过期刷新逻辑漏洞。核心结论是JWT安全性依赖实现细节,服务端必须硬编码算法白名单、使用高熵密钥、严格校验claims并建立撤销机制。建议采用非对称算法、DPOP令牌绑定等纵深防御策略。 综合评分: 95 文章分类: 漏洞分析,web安全,安全工具,红队,渗透测试
JWT 不是护身符:算法混淆与密钥爆破的那些坑
原创
amuxiaohuo amuxiaohuo
黑客网络安全
2026年8月25日 09:01 广东
在小说阅读器读本章
去阅读
【声明】本文内容仅用于授权安全测试、漏洞研究与防御教育。未经授权对任何真实系统进行测试均属违法行为。请在合法授权范围内使用所述技术。
JSON Web Token 已经成了现代 Web 应用的默认身份令牌格式。它无状态、跨域友好、前后端分离契合度高。但 JWT 的安全性高度依赖于实现细节:算法、密钥、校验逻辑、过期处理任何一环出错,都会让这把“无状态令牌”变成攻破身份体系的捷径。本文系统梳理 JWT 常见攻击面与防御要点。
一、JWT 结构与信任基础
一个 JWT 由三段 base64url 编码的部分用点号连接:header.payload.signature。header 声明算法(alg)和类型;payload 装载用户身份与 claims;signature 是服务端用 header.alg 指定的算法对前两段做的签名。服务端收到 token 后,用约定算法和密钥重新计算签名并比对。整个信任链条建立在“服务端会严格按预期校验”的假设上。而这个假设,恰恰是出问题最多的地方。
二、alg=none:被遗忘的历史后门
JWT 规范允许 alg 为 none,表示不签名。这本来是给调试或无安全性要求的场景设计的。但如果服务端校验库的实现把“alg 为 none 时不验签”这条逻辑也带进了生产,攻击者只要把 token 改成:
eyJhbGciOiJub25lIn0.eyJ1c2VyIjoiYWRtaW4ifQ.
(header 为 {“alg”:”none”},payload 为 {“user”:”admin”},签名为空)就能以任意身份通过校验。这类漏洞看似低级,但在一些自研或老旧的 JWT 库里仍时有出现,尤其是服务端逻辑写成“先读 alg,再分支选择验签方式”时,none 分支如果落到了“不验签直接信任”的实现上,就被打穿。
防御:服务端必须硬编码只接受指定算法(如 HS256 或 RS256),拒绝任何 alg 不在白名单内的 token;明确拒绝 alg=none。不要让 token 自己声明用什么算法来验签。
三、算法混淆:RS256 → HS256 的偷梁换柱
很多应用用非对称算法:服务端私钥签名,公钥验签(RS256/ES256)。如果校验库的 API 设计成“根据 token 的 alg 字段选择验签算法”,攻击者就能把 token 的 alg 从 RS256 改成 HS256,然后用服务端的公钥作为 HMAC 密钥重新签名。
为什么能成功?因为服务端校验逻辑读到 alg=HS256 后,会用 HMAC 算法、密钥为“公钥内容”去验签。公钥本身是公开的(常在 /.well-known/jwks.json 或前端 SDK 里),攻击者拿到公钥就能算出合法签名。而服务端本该用 RSA 公钥做非对称验签,却被 token 的 alg 字段骗去做了对称验签,公钥摇身一变成了 HMAC 密钥。
利用前提:服务端校验库允许 token 自声明算法、且公钥可被攻击者获取。修复方案同样是服务端固定算法,不根据 token 内容切换;使用库时显式指定 expected alg。
四、弱密钥与字典爆破
HMAC 类算法(HS256)的安全性完全取决于密钥强度。如果服务端用了一个弱密钥(如 secret、123456、应用名、或某个字典词),攻击者拿到任意一个有效 token,就能用 jwt_tool、hashcat 之类的工具做离线爆破。JWT 的签名是确定的 HMAC,爆破不需要与服务端交互,本地用 GPU 跑字典,几小时内能命中大量弱密钥。
拿到密钥后,攻击者可以为任意用户签发合法 token,服务端完全无法区分。这是一个比 alg=none 更常见的真实问题:开发者图省手把 JWT_SECRET 写成短字符串或硬编码进仓库,就成了整个身份体系的单点失败。
防御:HS256 密钥长度至少 32 字节且为高熵随机值;密钥从环境变量或 KMS 获取,禁止入库;更推荐使用非对称算法(RS256/ES256),私钥留在认证服务,其他服务只用公钥验签,减少密钥扩散面。
五、claims 伪造与kid 注入
header 里的 kid(key id)用于服务端选择验签密钥,常见于多密钥轮换场景。如果服务端把 kid 直接拼进文件路径或 SQL 查密钥,就会产生注入。比如:
key = read_file(‘/keys/’ + header[‘kid’] + ‘.pem’)
攻击者把 kid 设成 ../../public_key,可能读到非预期密钥;更严重的是结合算法混淆:先注入一个 kid 指向攻击者可控的公钥文件,再把 alg 改成 HS256,用该公钥做 HMAC 签名,形成完整利用链。
payload 里的 claims 同样不能盲信。很多新手开发者把 role/admin 这类字段直接放 payload 且服务端无校验,只要密钥泄露或 alg 可绕过,攻击者就能把 role 改成 admin。权限判定应当结合服务端会话或数据库,而非完全信赖 token 里的字段。
六、过期与刷新逻辑漏洞
JWT 无状态的代价是“撤销困难”。一个签发的 token 在过期前一直有效,即使用户改密码、登出,旧 token 仍可用。常见的缓解方案是维护一个黑名单或使用短有效期 + refresh token。但刷新逻辑本身常出问题:
-
refresh token 不轮换:每次刷新都返回新的 access token,但 refresh token 本身长期不变,一旦泄露相当于永久钥匙。正确做法是 refresh 时同时轮换 refresh token,旧的失效。
-
exp 校验缺失或被绕过:有的库默认不校验 exp,或服务端把 exp 当成“建议”而非“强制”。还有一种绕过是把 payload 里的 exp 改成很久以后的时间,如果服务端依赖客户端时间或未做服务端时间比对,就会被骗。
-
nbf/not-before 处理不当导致时间窗口攻击:在 token 刚签发的毫秒级窗口内,校验逻辑与签发逻辑的时间差可能被利用。
七、JWT 注入与会话固定
部分系统支持通过 cookie、URL 参数、Authorization 头三种方式传递 token。如果 URL 参数也被接受,就可能产生 JWT 通过 Referer/日志泄露的问题,以及会话固定攻击:攻击者把自己的 token 通过 URL 参数塞给受害者,受害者登录后若服务端用 URL 里的 token 而非新生成的,攻击者的会话就被“固定”成了受害者的会话。
防御:token 只通过 Authorization 头或 HttpOnly Secure cookie 传递;登录后强制重新签发 token(rotate on login);拒绝 URL 参数传递 token。
八、防御要点清单
- 算法白名单:服务端固定预期算法,拒绝 token 自声明;2. 密钥强度:HSM/KMS 管理密钥,定期轮换;3. claims 校验:iss/aud/exp/nbf 全部校验,权限以服务端为准;4. 撤销机制:维护短有效期 + 刷新轮换 + 黑名单/版本号机制(如用户改密码后全局 jti 失效);5. 库的选择:使用维护活跃的库(jose、java-jwt、jsonwebtoken 最新版),及时跟进 CVE;6. 传输安全:仅 HTTPS + HttpOnly cookie;7. 日志脱敏:token 不入日志,避免泄露即被重放。
DPoP 与令牌绑定:让窃取的 token 失效
JWT 无状态带来的“撤销困难”催生了一类新的防御方向:把 token 与持有者的密钥绑定,让窃取的 token 在别处无法使用。DPoP(Demonstration of Proof-of-Possession)是 OAuth 2.0 的扩展,客户端持有一对非对称密钥,每个请求用私钥对时间戳和 URL 签名,服务端校验签名与请求绑定。攻击者即便截获了 access_token,没有对应的私钥也无法构造合法的 DPoP 头,请求被拒。
类似机制还有 mTLS 令牌绑定(Token Binding over TLS),把 token 与客户端证书指纹绑定。这些方案增加了实现复杂度,但对高价值场景(金融、管理后台)是值得的纵深防御。本质上它们把“无状态令牌的安全性”从“密钥保密”升级为“密钥与持有者双因素”,让 JWT 在不牺牲无状态特性的同时获得接近有状态的撤销能力。
#
JWT 把身份状态从服务端搬到客户端,带来了架构上的便利,也把安全责任从“服务端会话表”转移到了“签名与校验逻辑”。它本身不是不安全,但每一个实现细节都是雷区:算法由谁来定、密钥有多强、claims 谁说了算、token 怎么撤销。把 JWT 当成“签了名就可以盲信”的银弹,是大多数 JWT 漏洞的根源。真正安全的做法是:把 JWT 当成一种传输格式,在其之上叠加完整的密钥管理、校验纪律与撤销策略,才能让无状态身份真正可靠。
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:黑客网络安全 amuxiaohuo amuxiaohuo《JWT 不是护身符:算法混淆与密钥爆破的那些坑》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。











评论