文章总结: 本文详述了pac4j-jwt组件CVE-2026-29000认证绕过漏洞。漏洞源于JwtAuthenticator解密JWE后未强制校验内层令牌签名,若内层为PlainJWT则跳过验证,攻击者可利用公钥伪造令牌。文章剖析了漏洞根因与攻击链,给出了升级修复版本、流量检测特征及临时缓解方案,强调加密不等于认证的安全设计原则。 综合评分: 100 文章分类: 漏洞分析,漏洞预警,解决方案
CVE-2026-29000:pac4j-jwt 认证绕过漏洞分析
原创
CVE-SEC CVE-SEC
CVE-SEC
2026年3月10日 08:01 四川
CVE-2026-29000:pac4j-jwt 认证绕过漏洞分析
漏洞概述
2026 年 3 月 4 日,开源 Java 安全框架 pac4j 官方发布安全公告,披露其 JWT 模块存在严重认证绕过漏洞,编号 CVE-2026-29000(GHSA-pm7g-w2cf-q238),CVSS v3.1 评分 10.0(Critical)。
该漏洞位于 pac4j-jwt 模块的 JwtAuthenticator 组件,攻击者无需任何凭据,仅凭服务器公开的 RSA 公钥,即可伪造任意身份的认证令牌,完全绕过身份认证机制。
受影响版本
| 分支 | 受影响版本 | 修复版本 | | — | — | — | | 4.x(JDK 8) | 4.0.0 – 4.5.8 | 4.5.9 | | 5.x(JDK 11) | 5.0.0 – 5.7.8 | 5.7.9 | | 6.x(JDK 17) | 6.0.0 – 6.3.2 | 6.3.3 |
pac4j 是 Java 生态中应用广泛的安全框架,被 Apereo CAS Server、Apache Knox、Apache Syncope 等知名项目集成使用。据互联网测绘数据,目前暴露在公网的相关资产超过 300 条。
背景知识
JWT(JSON Web Token) 分为三种形态:
- SignedJWT(JWS):对 Header+Payload 进行签名,格式为三段式
xxxxx.yyyyy.zzzzz,服务端验签后信任其 Claims。 - PlainJWT:不含签名,
alg字段值为none,格式为xxxxx.yyyyy.,尾部签名段为空。 - JWE(JSON Web Encryption):对整个 JWT 进行加密,格式为五段式,内层可嵌套 JWS 或 PlainJWT。
JwtAuthenticator 支持同时配置签名验证(signatureConfigurations)和加密解密(encryptionConfigurations)。在同时启用两者的场景下,正常业务流程是:先用私钥解密 JWE,再对内层 JWS 进行签名验证,两道关卡均通过才允许认证成功。
漏洞根因
漏洞的核心在于 JwtAuthenticator 对解密后内层令牌的类型判断存在逻辑缺陷。
以下是漏洞版本(6.3.2)的关键代码路径:
// JwtAuthenticator.java(漏洞版本)
JWT jwt = JWTParser.parse(token);
if (jwt instanceof EncryptedJWT) {
// 解密 JWE,得到内层明文
jwtObject = decryptToken((EncryptedJWT) jwt);
}
// 尝试将解密结果转为 SignedJWT
SignedJWT signedJWT = jwtObject.toSignedJWT();
if (signedJWT != null) {
// 签名验证块
verifySignature(signedJWT);
// ...
}
// signedJWT == null 时,直接跳过签名验证,提取 Claims
JWTClaimsSet claimsSet = jwtObject.getJWTClaimsSet();
问题出在 Nimbus JOSE+JWT 库的行为上:
- 当 JWE 内层是 SignedJWT 时,
toSignedJWT()返回非空对象,签名验证正常执行。 - 当 JWE 内层是 PlainJWT(
alg: none)时,toSignedJWT()返回null,签名验证块被完整跳过。
代码随后直接调用 getJWTClaimsSet() 提取声明,将攻击者在 PlainJWT 中写入的任意 sub、roles 等字段视为可信身份信息,完成认证。
触发该漏洞需满足一个前提:JwtAuthenticator同时配置了signatureConfigurations 和 encryptionConfigurations。仅配置其中一项的场景不受影响。
漏洞触发条件的特殊性
这里有一个值得关注的细节:JWE Header 中必须包含 "cty": "JWT" 字段。
该字段向 Nimbus 库声明内容类型为嵌套 JWT,触发库对内层数据执行 JWTParser.parse(),进而调用 toSignedJWT()。若缺少 cty: JWT,内层数据将作为普通字节流处理,走不到存在缺陷的分支。这也是攻击者构造 Payload 时需要精确控制的关键参数。
攻击流程
攻击分四步完成,整个过程无需任何有效凭据:
第一步:获取服务器 RSA 公钥
很多集成 pac4j-jwt 的应用会通过接口对外暴露 JWKS(JSON Web Key Set)端点,用于客户端验签。攻击者从该端点获取服务器的 RSA 公钥。
第二步:构造 PlainJWT
手工构造一个未签名的 JWT,alg 设为 none,Payload 中写入任意声明:
Header: {"alg": "none", "typ": "JWT"}
Payload: {"sub": "attacker_admin", "roles": ["ADMIN"], "exp": ...}
Token: base64url(Header).base64url(Payload).
第三步:用服务器公钥将 PlainJWT 包裹为 JWE
使用服务器 RSA 公钥对 PlainJWT 进行加密封装,生成 JWE。JWE Header 指定:
{
"alg": "RSA-OAEP-256",
"enc": "A256GCM",
"cty": "JWT",
"typ": "JWT"
}
由于加密使用的是公钥,任何人都可以执行这一步。
第四步:发送 JWE 令牌
将 JWE 作为 Bearer Token 提交至受保护接口:
Authorization: Bearer <JWE Token>
服务器用私钥解密 JWE 成功,解出 PlainJWT,toSignedJWT() 返回 null,签名验证跳过,攻击者以 attacker_admin 身份认证成功。
修复方案
官方修复(推荐)
升级至对应修复版本:
- pac4j-jwt 4.x 用户升级至 4.5.9
- pac4j-jwt 5.x 用户升级至 5.7.9
- pac4j-jwt 6.x 用户升级至 6.3.3
Maven 项目修改 pom.xml:
<dependency>
<groupId>org.pac4j</groupId>
<artifactId>pac4j-jwt</artifactId>
<version>6.3.3</version>
</dependency>
修复版本在解密 JWE 后,增加对内层令牌类型的显式校验:若 toSignedJWT() 返回 null(即内层为 PlainJWT),直接拒绝认证,不再提取 Claims。
临时缓解措施
若暂时无法升级,可考虑以下措施降低风险:
- 在应用层拦截含
alg: none特征的 Token(JWE Header 解码后检查); - 在 WAF 或网关层对五段式 JWE 结构中
cty=JWT的请求进行过滤告警; - 通过访问控制限制受保护接口的来源 IP 范围;
- 开启详细认证日志,监控异常身份登录(如出现未知的
sub值)。
检测方法
流量特征
JWE Token 为五段式 Base64url 结构(区别于 JWT 的三段式),可通过正则匹配:
^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$
对匹配的 Token,解码第一段(JWE Protected Header),检查是否同时含 alg: RSA-OAEP-256(或其他 RSA 算法)和 cty: JWT,出现则告警。
日志排查
检查应用认证日志中是否出现非预期的 sub 字段值,或在正常用户列表之外出现的认证成功记录。
漏洞存在性验证
在测试环境,执行以下命令验证是否暴露了 JWKS 端点:
curl http://<target>/pubkey
curl http://<target>/.well-known/jwks.json
若返回包含 RSA 公钥的 JSON,并且服务同时启用了 JWT 加密认证,则需优先检查版本并升级。
漏洞的本质
这个漏洞暴露了一个在安全设计中常见的认知误区:加密不等于认证。
JWE 只保证数据的机密性(不可被第三方读取),并不提供完整性或来源验证。签名(JWS)才是验证 Token 来源与内容未被篡改的机制。当两者被混合使用时,必须确保两道校验都被强制执行,任何一道的缺失都会导致安全边界被打破。
对于使用 pac4j-jwt 的团队,这次事件也提示了一个配置安全原则:同时启用签名和加密是一种增强安全的设计,但其正确实现依赖于框架对两者的强制串联校验。在依赖外部安全框架时,需关注版本更新和安全公告,而不能假设”配置了加密就配置了一切”。
时间线
| 时间 | 事件 | | — | — | | 2026-03-02 | pac4j 官方发布修复版本 4.5.9 / 5.7.9 / 6.3.3 | | 2026-03-04 | 官方安全公告发布,NVD 收录,VulnCheck 分析发布 | | 2026-03-05 | GitHub Security Advisory 正式收录 |
参考资料
- pac4j 官方安全公告:https://www.pac4j.org/blog/security-advisory-pac4j-jwt-jwtauthenticator.html
- GitHub Advisory:GHSA-pm7g-w2cf-q238
- NVD:CVE-2026-29000
- CWE-347:Improper Verification of Cryptographic Signature
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:CVE-SEC CVE-SEC CVE-SEC《CVE-2026-29000:pac4j-jwt 认证绕过漏洞分析》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。









评论