Skip to content
KitploitKITPLOIT
도구익스플로잇블로그
Log in
제출
도구익스플로잇블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

피드문의개인정보© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
CVE-2026-95663 — CVE-2026-95663에 대한 실행 가능한 개념 증명 재현기로, Apache Camel camel-keycloak이 토큰 만료 이후에도 캐시된 토큰 인트로스펙션 결과를 제공하던 문제를 다루며, Spring Boot 및 Quarkus 데모를 포함합니다. | Kitploit
도구/GitHubGitHub/oscerd/cve-2026-95663
Defensive ToolsVulnerability AnalysisWeb SecurityAuthenticationLearning & Education
GitHuboscerd/cve-2026-95663

CVE-2026-95663

CVE-2026-95663에 대한 실행 가능한 개념 증명 재현기로, Apache Camel camel-keycloak이 토큰 만료 이후에도 캐시된 토큰 인트로스펙션 결과를 제공하던 문제를 다루며, Spring Boot 및 Quarkus 데모를 포함합니다.

저장소 보기
1일 전아직 검토되지 않음

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

CVE-2026-95663 — camel-keycloak: 캐시된 introspection 결과가 토큰 만료 이후에도 제공됨

useTokenIntrospection=true로 토큰 introspection이 활성화된 KeycloakSecurityPolicy가 액세스 토큰이 만료된 후에도 계속 유효한 것으로 처리한 Apache Camel 취약점에 대한 실행 가능한 PoC 재현 코드입니다. 이는 캐시된 introspection 결과가 토큰보다 오래 유지되었기 때문입니다.

런타임디렉터리스택
Camel Spring Bootcamel-spring-boot/Spring Boot 3.5.13 + camel-keycloak 4.22.1
Camel Quarkuscamel-quarkus/Camel Quarkus 3.39.0 (Quarkus 3.39.0, Camel 4.22.0)

입증 내용

introspection 경로에서 Keycloak은 토큰의 exp가 지나면 해당 토큰을 inactive로 보고합니다. 따라서 만료를 강제하는 것은 active 플래그입니다. introspection 결과는 기본적으로 캐시되며(introspectionCacheEnabled=true, introspectionCacheTtl=60), 함께 제공되는 두 캐시(ConcurrentMapTokenCache, CaffeineTokenCache)는 항목이 삽입된 시점으로부터 고정된 시간이 지나면 만료시켰을 뿐, 캐시된 응답이 이미 담고 있던 exp 클레임으로 그 수명을 제한하지 않았습니다. 또한 KeycloakSecurityProcessor는 active만 확인했을 뿐 exp를 현재 시각과 비교하지 않았습니다.

따라서 토큰이 만료되기 직전에 캐시된 응답은 동일한 토큰을 지닌 이후 요청에 제공되었고, 해당 요청들은 만료된 토큰이 지니고 있던 역할과 권한으로 허용되었습니다. 이는 exp를 포함하는 응답이 그 시각을 넘어 캐시되어서는 안 된다고 명시한 RFC 7662에 위배됩니다.

cd camel-spring-boot          # or: cd camel-quarkus
mvn clean package
docker compose up -d --build
until [ "$(curl -s http://localhost:8080/exploit/ready)" = "Started" ]; do sleep 1; done
curl -s http://localhost:8080/exploit/attack      # takes ~4s: it waits for the token to expire
docker compose down

영향을 받는 빌드에서의 출력(두 런타임 모두 동일):

1) Request while the token is still valid
     introspection calls so far: 1
     outcome: [ADMITTED - the protected route ran]

   ... the token's exp has now passed. The cache entry is still inside its 60s TTL.

2) The same token again, now expired, against the SAME route
     introspection calls so far: 1  (unchanged - the endpoint was never asked again)
     outcome: [ADMITTED - the protected route ran]
     an expired token was admitted: true

3) CONTROL - the same expired token against a route with introspectionCacheEnabled=false
     introspection calls so far: 2  (the endpoint was asked)
     outcome: [REJECTED - CamelAuthorizationException: Token is not active (may be revoked or expired)]
     rejected once the endpoint was actually consulted: true

>>> PROVEN: ...

introspection 호출 카운터가 증거다. 이 카운터는 프로브 1과 프로브 2 사이에서 움직이지 않는다. 아이덴티티 공급자에게 두 번째로 질의한 적이 없으므로, 그 시점에는 이미 "비활성"인 공급자의 판정이 정책에 도달하지 않았다. 프로브 3은 그 판정이 존재함을 증명한다. 동일한 만료된 토큰을 캐싱이 꺼진 경로에 대해 사용하면 거부되는데, 이는 아직 업그레이드할 수 없는 배포 환경에 권고문이 제시하는 우회 방법이기도 하다. introspectionCacheTtl을 낮추는 것은 창을 좁힐 뿐 닫지는 않는다.

연결 방식

Keycloak 서버도, 네트워크도 없다. 앱은 Keycloak의 introspection 엔드포인트를 대신하는 스탠드인을 호스팅하며, 경로는 KeycloakTokenIntrospector가 구성하는 정확한 경로 ({serverUrl}/realms/{realm}/protocol/openid-connect/token/introspect)이고, Keycloak과 동일하게 동작한다. exp가 지나기 전까지는 active, 이후에는 inactive이며, 응답에는 exp, iss, realm_access.roles가 포함된다. 실제 KeycloakSecurityPolicy, 실제 KeycloakTokenIntrospector, 실제 캐시가 실행된다.

Introspection은 토큰이 JWT일 것을 요구하지 않으므로, 여기서의 토큰은 불투명한 문자열이다. 중요한 exp는 introspection 응답에 들어 있으며, 바로 그것을 캐시가 존중하지 못하고 있었다.

범위

이 문제는 토큰이 이미 지니고 있던 것 이상의 권한을 부여하지 않는다. 토큰 위조도, 권한 상승도 없다. 창은 introspectionCacheTtl(기본값 60초, 내부 서비스에 대한 문서의 권장 사항을 따른 경우 300~600초)에 의해 제한되며, 동일한 Camel 프로세스가 토큰이 아직 유효할 때 introspection하고 캐시한 경우에만 열린다. 토큰 introspection은 기본적으로 활성화되지 않는다. 따라서 심각도는 중간이다.

introspection이 비활성화된 경우 사용되는 로컬 JWT 검증 경로는 영향을 받지 않는다.

취약점 요약

속성값
구성 요소camel-keycloak (useTokenIntrospection=true인 KeycloakSecurityPolicy)
CWECWE-613 (불충분한 세션 만료)
심각도중간
공격 벡터호출자가 잠시 전까지 유효했던 bearer 토큰을 introspection 캐시의 TTL 내에서 다시 제시
영향토큰 만료 이후에도 해당 토큰이 지니고 있던 역할과 권한으로 요청이 허용됨
영향받는 버전4.16.0부터 4.18.5 이전, 4.19.0부터 4.22.2 이전
수정된 버전4.18.5, 4.22.2, 4.23.0
JIRACAMEL-24902
크레딧Andrea Cosentino from Apache Software Foundation

권고문: https://camel.apache.org/security/CVE-2026-95663.html

수정 내용

두 가지 독립적인 변경 사항:

  1. 두 캐시 구현 모두 이제 각 항목의 수명을 introspectionCacheTtl과 토큰의 exp까지 남은 시간 중 더 짧은 쪽으로 제한하며, 토큰이 이미 만료된 결과는 캐시에서 절대 제공되지 않는다.
  2. 캐시와 무관하게, KeycloakSecurityProcessor는 이제 introspection을 사용하는 모든 경로에서 exp가 과거인 토큰을 거부하므로, 로컬 JWT 검증 경로에서 이미 그러했던 것처럼 만료가 여기서도 강제된다.

exp 클레임이 없는 응답은 구성된 time-to-live를 유지한다.

main에서 apache/camel#26747 (7bfacb70)로 수정되었고, camel-4.22.x에는 #27182 (66fd7034)로, camel-4.18.x에는 #27183 (6be02c19)로 백포트되었다.

수정된 빌드 확인

camel.version을 4.22.2로 설정하고 다시 실행한다. 4.22.1 → 4.22.2에 대해 검증됨:

2) The same token again, now expired, against the SAME route
     introspection calls so far: 2
     outcome: [REJECTED - CamelAuthorizationException: Token is not active (may be revoked or expired)]
     an expired token was admitted: false

>>> NOT reproduced: the expired token was rejected.

카운터가 1에서 2로 증가하는 것에 주목하라. 캐시 항목의 수명은 토큰의 exp에 의해 제한되었으므로, 두 번째 요청은 다시 인트로스펙션을 수행하여 엔드포인트의 실제 판정을 받았다.

면책 조항

이 저장소는 교육 및 방어 목적으로 게시되었다. Apache Camel 사용자가 취약점을 이해하고, 영향을 받는지 확인하며, 업그레이드가 문제를 해결하는지 검증할 수 있도록 돕기 위함이다. 소유하거나 운영하지 않는 시스템에 이 자료를 사용하지 마라.

도구 다운로드