CVE-2026-29000:pac4j-jwt认证绕过漏洞分析

admin 2026-03-11 03:30:44 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文详述了pac4j-jwt组件CVE-2026-29000认证绕过漏洞。漏洞源于JwtAuthenticator解密JWE后未强制校验内层令牌签名,若内层为PlainJWT则跳过验证,攻击者可利用公钥伪造令牌。文章剖析了漏洞根因与攻击链,给出了升级修复版本、流量检测特征及临时缓解方案,强调加密不等于认证的安全设计原则。 综合评分: 100 文章分类: 漏洞分析,漏洞预警,解决方案


cover_image

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 内层是 PlainJWTalg: none)时,toSignedJWT() 返回 null,签名验证块被完整跳过。

代码随后直接调用 getJWTClaimsSet() 提取声明,将攻击者在 PlainJWT 中写入的任意 subroles 等字段视为可信身份信息,完成认证。

触发该漏洞需满足一个前提: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>
&nbsp; &nbsp;&nbsp;<groupId>org.pac4j</groupId>
&nbsp; &nbsp;&nbsp;<artifactId>pac4j-jwt</artifactId>
&nbsp; &nbsp;&nbsp;<version>6.3.3</version>
</dependency>

修复版本在解密 JWE 后,增加对内层令牌类型的显式校验:若 toSignedJWT() 返回 null(即内层为 PlainJWT),直接拒绝认证,不再提取 Claims。

临时缓解措施

若暂时无法升级,可考虑以下措施降低风险:

  1. 在应用层拦截含 alg: none 特征的 Token(JWE Header 解码后检查);
  2. 在 WAF 或网关层对五段式 JWE 结构中 cty=JWT 的请求进行过滤告警;
  3. 通过访问控制限制受保护接口的来源 IP 范围;
  4. 开启详细认证日志,监控异常身份登录(如出现未知的 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 认证绕过漏洞分析》

评论:0   参与:  0