Ошибка в подсчёте строк при обращении к базе данных позволяет обойти защиту от повторного использования одноразовых артефактов входа в Keycloak. Затронуты сборки 26.7.x до 26.7.4, развёрнутые в режиме без состояния с MySQL или MariaDB. Бюллетень GHSA-xpwp-2pcm-8xq3 опубликован 16 сентября 2026 года, исправление появилось в версии 26.7.4. Уязвимость получила идентификатор CVE-2026-90997 и высокую оценку по шкале CVSS (система оценки опасности уязвимостей). Вектор сетевой, сложность атаки высокая, влияние на конфиденциальность и целостность данных.
Уязвимость CVE-2026-90997
Keycloak - сервер управления учётными записями и единого входа. Через него корпоративные приложения проверяют сотрудников и получают токены доступа. В режиме без состояния сервер не держит сессии в памяти. Согласованность между копиями обеспечивает база данных. Поэтому такую схему часто выбирают для контейнерных платформ, где сервисы запускаются и останавливаются автоматически. Пока копий несколько, запросы распределяются свободно, и каждая из них опирается на общее хранилище. Всё, что относится к одноразовости учётных данных, ложится на запись в базу и на проверку этой записи.
Логика Keycloak полагается на число строк, которое драйвер базы данных сообщает после операции. С MySQL и MariaDB драйвер возвращает другое значение, чем ожидает приложение. Из-за расхождения запись об уже использованном артефакте не отбрасывается. Одноразовый артефакт проходит проверку повторно. В отчёте, приложенном к бюллетеню, это описано как несовпадение семантики подсчёта строк между драйвером и прикладным кодом.
Повторно предъявить можно JWT-утверждения клиента. JWT (веб-токен) - подписанный набор данных, которым клиент подтверждает свою личность. Также злоумышленник способен воспользоваться доказательствами владения ключом DPoP, механизмом подтверждения наличия приватного ключа у клиента, и одноразовыми кодами на основе времени TOTP, которые служат вторым фактором. Сначала артефакт нужно получить. Проще всего это сделать, встав между клиентом и сервером, то есть при атаке "человек посередине". Успешное повторное предъявление открывает доступ к конечной точке выдачи токенов или к процессу входа. На выходе злоумышленник получает токены доступа и обновления для чужой учётной записи.
Для эксплуатации нужны особые условия: перехват артефакта и подходящая конфигурация сервера. Привилегии не требуются, участия пользователя также не нужно. Из-за этого в векторе CVSS сложность атаки отмечена как высокая. Урон касается конфиденциальности и целостности, доступность сервиса не страдает. Обход политики безопасности выделен в бюллетене как отдельная категория риска: код приложения не выполняется, база напрямую не читается, однако защитный механизм перестаёт работать.
Значение одноразовости в системах единого входа велико. Токен предъявляется один раз, и повторное его использование сервер обязан отклонить. Коды на основе времени живут считаные секунды, потому перехватить и применить их нужно быстро. У JWT-утверждений и доказательств владения ключом окно шире. Именно поэтому ошибка в проверке записи меняет расстановку сил: у злоумышленника появляется время на повтор, а у защитного механизма исчезает основание для отказа.
Затронуты организации, которые держат Keycloak в режиме без состояния и подключили MySQL или MariaDB. Часто это кластеры Kubernetes, где сессии не закрепляются за отдельной копией сервиса. Развёртывания с сохранением состояния, а также сборки на других СУБД такой ошибке не подвержены. Для компании с единым входом в десятки внутренних сервисов последствия заметны: одна учётная запись открывает доступ сразу ко многим приложениям. Дальнейшие действия зависят от прав, которыми она наделена, и от того, какие системы ей доверяют.
Обновиться стоит до 26.7.4. Если сделать это быстро не получается, остаётся отключить режим без состояния. Такой шаг снижает отказоустойчивость, потому что балансировка перестаёт быть свободной, а копии сервиса начинают зависеть от общего хранилища сессий. Полезно также просмотреть журналы на повторные предъявления одноразовых артефактов и сократить срок жизни токенов. Шифрование канала между клиентом и сервером усложняет перехват, хотя не отменяет риск полностью: внутренние сегменты сети и скомпрометированные узлы остаются источником угрозы.
Расхождения между поведением драйвера и предположениями прикладного кода дают сбои в защитных механизмах. Проверки, построенные на побочных признаках вроде количества изменённых строк, хрупки при смене драйвера или СУБД. Надёжнее опираться на явные ограничения в схеме данных, которые не зависят от трактовки драйвера.
Ссылки