Skip to content
KitploitKITPLOIT
ИнструментыБлог
Отправить
ИнструментыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
Инструменты/GitHubGitHub/ivanesk315/cve-2026-18963
Анализ уязвимостейЭксплуатацияЭксплуатация веб-приложенийВеб-безопасностьТестирование на ПроникновениеУправление идентификацией и доступом (IAM)АутентификацияОбучение и ОбразованиеЛаборатории и Практика
GitHubivanesk315/cve-2026-18963

CVE-2026-18963

Лаборатория на базе Docker и эксплойт на Python для CVE-2026-18963 — обход процедуры сброса учётных данных в Keycloak, позволяющий захватить аккаунт через обход проверки электронной почты.

0 дней назадЕщё не проверено
Репозиторий

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться

CVE-2026-18963 — Лаборатория обхода потока сброса учётных данных Keycloak

Обзор

Лаборатория моделирует уязвимость CVE-2026-18963 (CVSS 9.1) в Keycloak, позволяющую злоумышленнику захватить любую учётную запись через обход проверки электронной почты в потоке сброса пароля.

Только для целей исследования безопасности и обучения.

Требования

  • Docker & Docker Compose
  • Python 3.8+
  • pip

Инструкция по использованию

1. Запуск уязвимого Keycloak

root@kitploit:~
docker-compose up -d

Дождитесь запуска Keycloak (~30-60 секунд).

2. Настройка лаборатории

root@kitploit:~
pip install -r requirements.txt
python setup-lab.py

Скрипт создаст:

  • Realm vuln-lab с включённым reset-password
  • Настройку SMTP (MailHog) для отправки email
  • Пользователя victim ([email protected] / VictimPass123!)

3. Запуск эксплойта

root@kitploit:~
python exploit.py -u http://127.0.0.1:8080 -r vuln-lab -t victim -p Pwned123!

Опции:

  • -u / --url: URL Keycloak (по умолчанию: http://127.0.0.1:8080)
  • -r / --realm: Имя realm (по умолчанию: vuln-lab)
  • -t / --target: Имя целевого пользователя (по умолчанию: victim)
  • -p / --password: Новый пароль (по умолчанию: Pwned123!)
  • -v / --verbose: Включить отладочный вывод

4. Просмотр email (опционально)

MailHog UI: http://127.0.0.1:8025 — просмотр email сброса пароля, отправленных в процессе эксплойта.

5. Очистка

root@kitploit:~
docker-compose down -v

Технические детали

Первопричина

Две ошибки в Keycloak в совокупности образуют цепочку атаки:

Ошибка 1 — Повреждение состояния селектора (DefaultAuthenticationFlow.java): Когда пользователь нажимает "Try Another Way", auth note AUTHENTICATION_SELECTOR_SCREEN_DISPLAYED сохраняется как "true" (строковое булево значение) вместо ID модели выполнения. Значение "true" не привязано ни к какому конкретному выполнению, поэтому оно сохраняется на протяжении всех шагов потока, из-за чего селектор отображается в неверном контексте.

Ошибка 2 — Безусловный успех действия (ResetCredentialEmail.java): Метод action() в ResetCredentialEmail вызывает context.success() безусловно, не проверяя action token. Обычно action() вызывается только когда пользователь нажимает ссылку в email (с action token). Но когда селектор повреждён, атакующий может вызвать action() напрямую через обработку потока.

Подробная цепочка атаки

root@kitploit:~
Attacker                              Keycloak
   │                                     │
   │─── GET /auth (OIDC + PKCE) ────────>│  1. Инициализация auth-сессии
   │<── Login page + cookies ────────────│
   │                                     │
   │─── GET /reset-credentials ─────────>│  2. Переход к потоку сброса
   │<── Username form ──────────────────│
   │                                     │
   │─── POST tryAnotherWay=on ─────────>│  3. Повреждение состояния селектора
   │<── Authenticator selector ─────────│     SELECTOR_DISPLAYED = "true"
   │                                     │
   │─── POST username=victim ──────────>│  4. Отправка username через селектор
   │<── "Check your email" page ────────│     Email отправлен, CURRENT_EXEC = email_id
   │                                     │
   │─── GET /reset-credentials ────────>│  5. Повторный вход в поток сброса
   │<── Corrupted selector (!!!) ───────│     processFlow() видит SELECTOR="true"
   │                                     │     → отображает селектор для шага email
   │                                     │
   │─── POST {} (empty body) ──────────>│  6. BYPASS: вызов action()
   │<── 302 → UPDATE_PASSWORD ─────────│     processAction() не находит
   │                                     │     authenticationExecution в форме
   │─── GET /required-action ──────────>│     → попадает в ветку action()
   │<── Password update form ──────────│     ResetCredentialEmail.action()
   │                                     │     → context.success() (безусловно!)
   │                                     │     → поток переходит к ResetPassword
   │                                     │
   │─── POST password-new=Pwned! ──────>│  7. Установка нового пароля
   │<── 302 → /account/ ──────────────│     Захват учётной записи завершён
   │                                     │
   └── Вход с новым паролем ────────────┘

Почему работает шаг 6?

В DefaultAuthenticationFlow.processAction() при получении POST:

  1. Проверка tryAnotherWay в форме → НЕТ (форма пуста)
  2. Проверка authenticationExecution в форме → НЕТ (форма пуста)
  3. Попадание в последнюю ветку: вызов authenticator.action(result) для модели из URL

Поскольку URL содержит execution=<email_exec_id> (из action формы селектора), вызывается ResetCredentialEmail.action() → возвращает context.success() → поток переходит к ResetPassword → отображается форма установки пароля.

Уязвимые версии

ПродуктУязвимИсправлено
Keycloak (upstream)< 26.7.226.7.2+
RHBK 26.4.x< 26.4.1526.4.15+
RHBK 26.6.x< 26.6.626.6.6+

Патч (PR #51844)

DefaultAuthenticationFlow.java:

  • setAuthNote(SELECTOR_DISPLAYED, "true") → setAuthNote(SELECTOR_DISPLAYED, model.getId())
  • processFlow() проверяет selector.equals(lastExecutionId) вместо Boolean.parseBoolean()
  • Если не совпадает → removeAuthNote(SELECTOR_DISPLAYED)

ResetCredentialEmail.java:

  • action() проверяет ACTION_TOKEN_USER_ID перед вызовом context.success()
  • Если нет действительного action token → context.failure(INVALID_USER)

Ссылки

  • NVD - CVE-2026-18963
  • Red Hat CVE Page
  • Keycloak Issue #51833
  • Fix PR #51844
  • Kudelski Security Research
  • The Hacker News
Скачать инструмент