Keycloak 계정 탈취 취약점(CVE-2026-18963)
■ 서론
2026년 8월, 여러 애플리케이션의 사용자 인증을 통합 관리하는 오픈소스 인증 플랫폼 Keycloak에서 계정 탈취가 가능한 취약점(CVE-2026-18963)이 공개됐다. 해당 취약점의 심각도는 CVSS 9.1로 평가되었다. 이 취약점은 비밀번호 재설정 과정에서 이메일을 통한 본인 확인 단계를 우회할 수 있다. 이를 악용하면 공격자는 피해자의 이메일에 접근하지 않고도 인증 절차를 건너뛰어 임의 계정의 비밀번호를 재설정 및 계정 탈취가 가능하다.
Keycloak은 SSO(Single Sign-On)를 중심으로 OAuth 2.0, OpenID Connect, SAML 등 표준 프로토콜 기반의 인증·인가와 사용자 계정 관리 기능을 제공한다. GitHub Star 약 3만 6천개를 보유할 만큼 널리 알려져 있으며, 개인뿐 아니라 기업과 기관의 서비스 인증 기반으로 폭넓게 사용된다.
그림 1. Keycloak GitHub Star
이 취약점은 취약 버전의 Keycloak을 통해 비밀번호 찾기 기능이 활성화된 환경에서 악용된다. 이 기능은 로그인 페이지에 노출되어 있어, 공격자는 인증 없이 대상의 사용자명이나 이메일 주소만으로 관리자 계정을 포함한 임의 계정 탈취가 가능하다. 따라서 해당 환경에서는 취약 버전 사용 여부를 확인하고 수정된 버전으로 업그레이드해야 한다.
■ 영향받는 소프트웨어 버전
CVE-2026-18963에 취약한 소프트웨어는 다음과 같다.
| S/W 구분 | 취약 버전 |
|---|---|
| Keycloak | 26.0.0 <= version < 26.4.15 26.5.0 <= version < 26.6.6 26.7.0 <= version < 26.7.2 |
| Red Hat Build of Keycloak | 26.4.0 <= version < 26.4.15 26.6.0 <= version < 26.6.6 |
■ 공격 시나리오
그림 2. 공격 시나리오
① 공격자는 피해자 계정의 비밀번호 재설정을 요청한다. ② 공격자는 이전 요청에서 인증 세션에 남은 상태값을 악용해 이메일 인증을 우회한다. ③ 우회에 성공한 공격자는 피해자 계정의 새 비밀번호를 설정한다. ④ 공격자는 변경한 비밀번호로 피해자 계정에 로그인하여 계정을 탈취한다. |
|---|
■ 테스트 환경 구성 정보
피해자 서버는 취약한 Keycloak 26.7.1을 Docker 컨테이너로 구동한다. 공격자는 피해자 서버에 접근 가능한 호스트라면 어디서든 공격할 수 있으며, 해당 테스트에서는 동일 네트워크상의 Kali Linux 컨테이너를 사용한다.
| 이름 | 정보 |
|---|---|
| 피해자 | Keycloak 26.7.1 (172.17.0.2:9105) |
| 공격자 | Kali Linux (172.17.0.3) |
■ 취약점 테스트
Step 1. 취약 환경 구성
먼저 피해자 환경을 구성한다. 다음 명령어로 CVE-2026-18963에 취약한 Keycloak 26.7.1을 로그인에 사용하는 웹사이트 컨테이너를 구동한다.
> git clone https://github.com/EQSTLab/CVE-2026-18963.git > cd CVE-2026-18963 > docker build -t cve-2026-18963 . > docker run -d --name cve-2026-18963 -p 9105:9105 cve-2026-18963 |
|---|
http://172.17.0.2:9105을 통해 로그인 기능이 있는 웹 페이지에 접근한다.
그림 3. 공격 대상 웹 페이지 확인
로그인 버튼을 누르면 Keycloak 로그인 페이지로 이동하며, 이 웹사이트가 인증을 Keycloak에 위임하고 있음을 확인할 수 있다. 이때 로그인 페이지에 공격에 사용되는 비밀번호 찾기 기능이 활성화되어 있는 것도 드러난다.
그림 4. 피해자 Keycloak 로그인 페이지
Step 2. 공격 수행 및 결과 확인
공격자는 다음과 같이 임의 계정의 비밀번호를 변경하는 스크립트를 실행한다.
> git clone https://github.com/EQSTLab/CVE-2026-18963.git > cd CVE-2026-18963 > python3 exploit.py [username] [new-password] --url http://[target-ip]:9105 |
|---|
그 결과 입력한 계정의 비밀번호가 바뀌어, 공격자가 피해자 계정을 탈취하게 된다.
그림 5. 피해자 계정 탈취
■ 취약점 상세 분석
Step 1. 공격 흐름
이 취약점은 비밀번호 재설정 과정에서 인증 수단 선택 화면 표시 여부를 기록하는 상태값이 해당 단계 종료 후에도 정리되지 않고 다른 인증 단계까지 남아 악용되면서 발생한다. 공격 흐름을 이해하기 위해 먼저 Keycloak의 비밀번호 재설정 단계와 공격에 사용되는 주요 상태값을 살펴본다.
Keycloak의 비밀번호 재설정은 계정 입력, 메일을 통한 본인 확인, 새 비밀번호 설정 순으로 진행된다. 각 단계를 실행 단계(Execution)라 하고, 단계마다 실행 단계 ID(Execution ID)가 붙는다. 주요 실행 단계는 다음과 같다.
| 순서 | 정보 | 정보 |
|---|---|---|
| 1 | reset-credentials-choose-user (계정 입력 단계) | 비밀번호 재설정 대상 계정을 입력 |
| 2 | reset-credential-email (메일 발송 단계) | 비밀번호 재설정 링크 전송 및 본인 여부 검증 |
| 3 | reset-password (비밀번호 재설정 단계) | 새 비밀번호를 설정 |
각 단계는 앞 단계가 성공적으로 완료돼야 다음 단계로 넘어간다. 처리 및 검증은 인증 세션(authentication session)에 저장된 단계별 진행 상태값을 기준으로 수행된다. 인증 세션은 로그인, 비밀번호 재설정 등 인증 흐름을 진행하는 동안 유지되는 브라우저 탭 단위 세션으로, URL의 tab_id로 식별된다. 서버는 요청마다 tab_id로 세션을 찾아, 그 안에 저장된 상태값을 근거로 지금 어느 단계이고 다음에 무엇을 해야 할지 판단한다.
이번 취약점에서 악용되는 상태값은 다음과 같다.
| 상태값 | 의미 |
|---|---|
| current.authentication.execution | 현재 처리 중인 실행 단계의 ID |
| auth.selector.screen.rendered | 인증 수단 선택 화면의 표시 여부 |
auth.selector.screen.rendered가 나타내는 인증 수단 선택 화면은 현재 실행 단계에서 진행할 수 있는 동작을 사용자에게 제시하고 그중 하나를 선택받는 화면이다. 아래에서는 PoC의 요청을 순서대로 따라가며 계정 입력 단계에서 생성된 이 상태값이 메일 발송 단계까지 어떻게 이어지는지 확인한다.
그림 6. 공격 흐름
① 서버 세션의 인증 수단 선택 화면 상태값 생성 유도
비밀번호 재설정 폼에 tryAnotherWay=on을 전송하고, 이후 같은 인증 세션을 다시 사용하기 위해 tab_id를 복사해둔다.
그림 7. tryAnotherWay 전송
tryAnotherWay=on을 처리하기 전 인증 세션에는 진행 단계 관련 값만 존재한다.
그림 8. 요청 처리 전 인증 세션
요청을 처리한 뒤에는 인증 세션에 auth.selector.screen.rendered = "true"가 저장되어, 서버가 인증 수단 선택 화면을 표시해야 하는 상태임을 기억한다.
그림 9. 요청 처리 후 인증 세션
② 비밀번호 재설정 대상 지정 및 세션 유지
표시된 인증 수단 선택 화면에서 항목을 선택해 요청을 제출할 때, POST 본문에 비밀번호를 재설정할 대상인 username=victim을 추가하고 authenticationExecution 필드는 제외한다. 정상적인 제출과 달리 이 필드를 빼면, 앞서 저장된 인증 수단 선택 화면 상태값이 제거되지 않고 세션에 그대로 유지된다.
그림 10. authenticationExecution 삭제 후 username 전송
서버는 이 제출을 계정 입력 단계의 처리로 받아 username=victim을 재설정 대상으로 저장한다.
그림 11. 인증 세션에 저장된 재설정 대상
이어서 흐름은 메일 발송 단계로 진행되어 재설정 메일이 발송되고, 세션의 현재 단계도 메일 발송 단계로 갱신된다. 이때 인증 수단 선택 화면 상태값은 계정 입력 단계에서 저장된 채 제거되지 않은 채 남아 있다
③ 비밀번호 재설정 흐름 재진입
저장해 둔 tab_id로 비밀번호 재설정 페이지에 다시 접근하여, 앞선 요청에서 사용한 동일한 인증 세션을 불러온다.
그림 12. tab_id로 조작된 서버 세션을 다시 호출
이 세션에는 인증 수단 선택 화면 상태값과 메일 발송 단계를 가리키는 현재 실행 단계 ID가 남아 있다. 서버는 이 값을 기반으로 인증 수단 선택 화면을 생성하는데, 현재 단계에서 택할 수 있는 동작이 메일 발송뿐이라 메일 발송 선택지가 담긴 선택 화면이 만들어진다.
그림 13. 메일 발송 단계의 인증 수단 선택 화면
④ 메일 링크 확인 없이 비밀번호 재설정
메일 발송 단계 인증 수단 선택 화면의 폼에서도 authenticationExecution을 삭제하고 전송한다.