Макросъёмка платы сервера с треснувшим разъёмом и лазерной гравировкой «CVE-2026-33757 · SESSION FIXATION» на радиаторе, подсвеченная лампой лупы на чёрном антистатическом коврике. Красный индикато...


На аудите fintech-проекта, где OpenBao крутил ротацию database credentials и API-ключей облачных провайдеров, я ковырял OIDC-аутентификацию через Burp Suite и наткнулся на роль с явно включённым callback_mode=direct (не дефолт - кто-то из админов выставил руками). Когда в марте 2026 вышел advisory по CVE-2026-33757 с CVSS 9.6 Critical, я проверил сценарий на тестовом стенде - воспроизвёл за полтора часа: фишинговая ссылка, один клик жертвы, и OpenBao отдаёт vault token с полным доступом к secrets engine. Без единого алерта в аудит-логе, потому что никто не настроил корреляцию IP в auth flow. Разберём механику, пошаговый сценарий эксплуатации и конкретные шаги по детектированию - этот кейс с session fixation хорошо ложится в общую картину, которую я собрал в гайде по атакам на аутентификацию.

Бизнес-логика атаки: зачем фиксировать сессию в secrets vault​

OpenBao - open-source форк HashiCorp Vault, появившийся после смены лицензии Vault на BSL. Многие организации перетащили инфраструктуру на OpenBao именно из-за лицензионных ограничений, и теперь он централизованно хранит самое ценное: API-ключи, пароли баз данных, TLS-сертификаты, токены облачных провайдеров.

Если в инстансе OpenBao есть хотя бы одна роль с явно включённым callback_mode=direct (это не дефолт - администратор задаёт вручную), компрометация vault token через session fixation - прямой путь к credentials сервисов, обращающихся к secrets engine:
  • Через vault token атакующий читает database credentials, SSH-ключи, cloud provider API keys
  • С этими credentials делает lateral movement без необходимости ломать каждый сервис отдельно
  • При наличии write-политик подменяет секреты, внедряя backdoor credentials для persistence
  • В средах с CI/CD интеграцией один vault token каскадно компрометирует весь pipeline деплоя
По MITRE ATT&CK цепочка: Exploit Public-Facing Application (T1190, Initial Access) -> Steal Web Session Cookie (T1539, Credential Access) - получение vault token через перехват OIDC callback -> доступ к Cloud Accounts (T1078.004) -> lateral movement с полученными credentials (T1550.004).

Анатомия CVE-2026-33757: OIDC callback без подтверждения пользователя​

1785563616219.webp

Уязвимость классифицирована как CWE-384 (Session Fixation): "Authenticating a user, or otherwise establishing a new user session, without invalidating any existing session identifier gives an attacker the opportunity to steal authenticated sessions.""Аутентификация пользователя или иное создание нового сеанса без аннулирования существующего идентификатора сеанса дает злоумышленнику возможность перехватить аутентифицированные сеансы." Последствие по CWE - Gain Privileges or Assume Identity.

OpenBao поддерживает аутентификацию через JWT/OIDC с несколькими режимами callback. В стандартном режиме пользователь инициирует вход, OpenBao перенаправляет в IDP, после аутентификации callback возвращается в браузер пользователя, который подтверждает вход. В direct mode (callback_mode=direct) callback идёт напрямую в API OpenBao, минуя подтверждение в браузере.

Суть проблемы: в версиях до 2.5.2 при callback_mode=direct OpenBao не запрашивает подтверждение пользователя. Атакующий инициирует аутентификационный запрос, получает auth URL и отправляет его жертве. Жертва кликает, аутентифицируется в IDP - а OpenBao выдаёт токен в сессию, которую контролирует атакующий. Flow построен на authorization code grant, но direct mode позволяет атакующему поллить API до получения токена.

Затронутый пакет по данным OSV.dev: (openbao/openbao, Go), все версии до коммита e32103951925. Фикс вошёл в релиз 2.5.2.

Разбор CVSS-вектора​

CVSS 3.1: 9.6 (Critical) - вектор CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:L

КомпонентЗначениеЧто это значит на практике
AV:NNetworkАтака через сеть - физический доступ не нужен
AC:LLowНет специальных условий, кроме наличия роли с direct mode
PR:NNoneЛюбой может инициировать OIDC auth request, привилегии не требуются
UI:RRequiredЖертва должна кликнуть по ссылке и аутентифицироваться в IDP
S:CChangedЧерез украденные секреты атакуются другие системы за пределами OpenBao
C:HHighПолный доступ к секретам в рамках политик жертвы
I:HHighМодификация секретов при наличии write-политик
A:LLowМинимальное влияние на доступность самого vault

По EPSS, вероятность эксплуатации в течение 30 дней - 0.41% (percentile 33.76%). CISA оценивает technical impact как total при отсутствии подтверждённой эксплуатации в дикой природе (Exploitation: none) и невозможности полной автоматизации (Automatable: no). SSVC-решение: Track - мониторить.

Числа EPSS тут обманчивы. Нишевость OpenBao по сравнению с коммерческим Vault снижает интерес массовых атакующих, но для целевых атак на организации, мигрировавшие на OpenBao, вектор остаётся рабочим. Массовая эксплуатация - маловероятна, точечная - вопрос времени.

Штатный OIDC flow vs эксплуатация session fixation​

1785563639647.webp

Штатный OIDC flow (стандартный callback):
  1. Пользователь запрашивает вход в OpenBao через CLI или UI
  2. OpenBao генерирует auth URL с параметрами state, nonce, redirect_uri
  3. Браузер пользователя перенаправляется в IDP (Keycloak, Okta, Azure AD)
  4. Пользователь аутентифицируется в IDP
  5. IDP возвращает authorization code в браузер пользователя через redirect
  6. Браузер пользователя отправляет code обратно в OpenBao
  7. OpenBao обменивает code на ID token, проверяет state/nonce, выдаёт vault token
  8. Vault token получает пользователь, инициировавший flow
Эксплуатация через callback_mode=direct:
  1. Атакующий инициирует auth request к API, получает auth URL с state и nonce
  2. Атакующий отправляет auth URL жертве (фишинг, мессенджер, email)
  3. Жертва кликает, аутентифицируется в IDP
  4. IDP возвращает authorization code напрямую в API OpenBao, а не в браузер жертвы
  5. OpenBao привязывает vault token к сессии, инициированной атакующим
  6. Атакующий поллит API и получает vault token жертвы
Вся разница - в direct mode IDP callback идёт в API, а не в браузер. OpenBao не запрашивает подтверждение: кто инициировал flow, тот и получает token. Session fixation через OIDC в чистом виде.

Шаг 1. Recon - fingerprinting роли с callback_mode=direct.
Атакующий запрашивает конфигурацию OIDC-ролей. Если ACL позволяет - через bao list auth/oidc/role, затем bao read auth/oidc/role/<name> для каждой роли. Ищем callback_mode: "direct".

Шаг 2. Инициация auth flow от имени атакующего.
Код:
GET /v1/auth/oidc/oidc/auth_url?role=<TARGET_ROLE>&redirect_uri=<CALLBACK_URI> HTTP/1.1
Host: openbao.target.internal:8200
OpenBao возвращает URL для аутентификации в IDP с параметрами state и nonce. Атакующий сохраняет их для поллинга на шаге 5.

Шаг 3. Доставка фишинговой ссылки жертве.
Auth URL выглядит как легитимная ссылка на корпоративный IDP - жертва видит знакомый экран логина Keycloak, Okta или Azure AD. Визуально ничего подозрительного: домен IDP корректный, TLS-сертификат валидный. Ни один email-фильтр не заблокирует ссылку на ваш собственный корпоративный IDP.

Шаг 4. Жертва аутентифицируется в IDP.
После ввода credentials IDP выполняет redirect с authorization code. В direct mode этот code уходит напрямую в API OpenBao, а не в браузер жертвы. Если у жертвы уже есть активная SSO-сессия в IDP - аутентификация происходит автоматически, без ввода пароля. Один клик - и всё.

Шаг 5. Атакующий поллит API для получения токена.
Bash:
# Упрощённая иллюстрация механики поллинга (не рабочий PoC).
# В реальном flow IDP доставляет authorization code напрямую в API OpenBao
# через redirect; атакующий опрашивает статус по state, не передавая code.
while true; do
  RESULT=$(curl -s "https://openbao.target.internal:8200/v1/auth/oidc/oidc/poll?state=$STATE")
  echo "$RESULT" | grep -q client_token && break
  sleep 2
done
echo "$RESULT"
Как только жертва завершает аутентификацию, OpenBao отдаёт vault token в ответ на polling-запрос.

Шаг 6. Доступ к secrets engine.
Полученный token используется для операций в рамках политик жертвы: bao kv get -mount=secret <path>, bao read database/creds/<role> и т.д.

Предусловия и ограничения​

Работает если:
  • OpenBao версии до 2.5.2
  • Существует хотя бы одна OIDC-роль с callback_mode=direct
  • Жертва имеет активную SSO-сессию в IDP или готова аутентифицироваться
  • OpenBao API доступен атакующему по сети
Не работает если:
  • Все роли используют стандартный callback mode
  • IDP принудительно запрашивает consent для каждой сессии по Client ID, используемому OpenBao
  • OpenBao обновлён до 2.5.2 (добавлен экран подтверждения для direct-логинов)
  • Сетевая сегментация блокирует доступ атакующего к API OpenBao
OPSEC-заметка: атака оставляет следы в аудит-логах OpenBao (auth request, token creation) и логах IDP. Два разных source IP обращаются к одному auth flow - это IoC при корректно настроенном мониторинге. Фишинговый URL ведёт на легитимный домен IDP, что затрудняет обнаружение на стороне email security, но не на стороне vault.

Место в цепочке атаки​

CVE-2026-33757 сидит между initial access и credential access:
  1. Recon - обнаружение OpenBao инстанса, fingerprinting OIDC-ролей с callback_mode=direct
  2. Initial Access (T1190) - эксплуатация уязвимого OIDC flow через фишинг
  3. Credential Access (T1539) - получение vault token с правами жертвы
  4. Privilege Escalation - если политики жертвы включают admin-уровень, атакующий получает полный контроль над secrets engine
  5. Lateral Movement (T1550.004) - credentials из secrets engine (database passwords, API keys, SSH keys) открывают доступ к другим системам
  6. Exfiltration - массовое чтение секретов через vault API
Атака особенно опасна в средах, где OpenBao хранит credentials для CI/CD pipeline (Jenkins, GitLab CI), cloud provider API keys (AWS IAM, GCP Service Accounts) или database root passwords. Один vault token каскадно компрометирует десятки сервисов - это не локальная бага, а точка входа для захвата инфраструктуры.

Детектирование через аудит-логи OpenBao​

OpenBao ведёт аудит-лог всех операций через audit device. Для поиска session fixation нужны три IoC:

IoC 1: Auth request и token issuance с разных IP. Запрос на /v1/auth/oidc/oidc/auth_url приходит с одного remote_address (атакующий), а IDP фиксирует аутентификацию с другого IP (жертва). Корреляция request.id и remote_address в аудит-логах выявляет расхождение.

IoC 2: Polling-паттерн на callback endpoint. Множественные запросы к /v1/auth/oidc/oidc/callback с одними и теми же параметрами state/nonce в короткий промежуток. Штатный flow - один callback, а не серия.

IoC 3: Использование token с нехарактерного IP. После получения vault token операции с секретами выполняются с IP, отличного от обычного для этого пользователя. Корреляция auth.client_token с remote_address в аудит-логах обнаруживает аномалию.

Для SIEM-интеграции: фильтруйте записи по path: "auth/oidc/*", группируйте по request.id и remote_address. Аномалия - два и более уникальных IP в рамках одного auth flow. Для Elastic SIEM 8.x+ правило строится через EQL-запрос по event.action и source.ip с correlation window 5-10 минут.

Сравнение мер устранения​

МераЗакрывает уязвимостьПобочные эффектыВремя внедрения
Обновление до 2.5.2Да - полностьюТребует тестирования в staging1-4 часа
Удаление callback_mode=directДа - полностьюЛомает automated auth flows, зависящие от direct mode15 минут
Consent prompt в IDPЧастично - снижает рискДополнительный шаг при каждом входе всех пользователей30 минут
Сетевая сегментация APIНет - снижает attack surfaceНе устраняет саму уязвимость, ограничивает доступ2-8 часов

Чеклист устранения CVE-2026-33757​

📚 Часть контента скрыта. Этот материал доступен участникам сообщества с рангом One Level или выше
Получить доступ просто — достаточно зарегистрироваться и проявить активность на форуме

Минилаб для отработки​

Требования к окружению:
  • Docker и Docker Compose
  • RAM: 4 ГБ минимум, 8 ГБ рекомендуется (OpenBao + Keycloak + Burp Suite)
  • ОС: GNU/Linux (Ubuntu 22.04+), macOS или Windows с WSL2
  • Burp Suite Community/Pro или mitmproxy для перехвата HTTP-запросов
  • Сеть: локальная, интернет не нужен после скачивания образов
Сценарий воспроизведения:
  1. Поднять OpenBao в dev-режиме: docker run -d --name openbao -p 8200:8200 openbao/openbao server -dev. Dev-режим автоматически unseal'ит vault и выдаёт root token в stdout
  2. Поднять Keycloak как IDP: docker run -d --name keycloak -p 8080:8080 -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin quay.io/keycloak/keycloak start-dev
  3. Настроить в Keycloak: создать realm, OIDC client с redirect URI на callback endpoint OpenBao, тестового пользователя
  4. Сконфигурировать OIDC auth method в OpenBao: включить auth/oidc, создать роль с callback_mode=direct, указать oidc_discovery_url от Keycloak, привязать token_policies
  5. Открыть Burp Suite, настроить proxy для перехвата запросов к OpenBao API на порту 8200
  6. В терминале (имитация атакующего) выполнить GET-запрос на /v1/auth/oidc/oidc/auth_url с нужной ролью, сохранить state и nonce из ответа
  7. В другом браузере (имитация жертвы) перейти по полученному auth URL, аутентифицироваться в Keycloak
  8. Наблюдать в Burp: callback приходит в API, token выдаётся в сессию «атакующего»
  9. Проверить доступ: использовать полученный token для bao kv get
Верификация фикса: обновить контейнер OpenBao до 2.5.2, повторить шаги 6-8. На шаге 7 должен появиться экран подтверждения, блокирующий автоматическую выдачу token без явного согласия пользователя.

Session fixation - уязвимость, которая на бумаге выглядит элементарно: не привязал session ID к инициатору, не запросил подтверждение - и auth flow развалился. CWE-384 существует больше пятнадцати лет. И при этом проект уровня OpenBao - штука, которая по определению хранит credentials всей организации - выпускает auth-метод с callback_mode=direct без подтверждения пользователя. Это не рядовая бага, а архитектурный просчёт в auth-flow.

EPSS показывает 0.41%, CISA ставит Exploitation: none - и может сложиться ощущение, что угроза теоретическая. Но развернуть PoC - вопрос двух часов, доставка фишинговой ссылки - одного письма, а auth URL ведёт на легитимный домен IDP, который не заблокирует ни один email-фильтр.

Для организаций, мигрировавших с Vault после смены лицензии HashiCorp, проверка занимает две минуты: bao list auth/oidc/role и bao read auth/oidc/role/<name>. Две минуты вместо расследования инцидента с утечкой всех secrets. Я ожидаю, что в ближайший год мы увидим аналогичные баги в других форках и альтернативах Vault - молодые проекты наследуют кодовую базу, но не всегда наследуют зрелость security review.
 
Последнее редактирование:
Мы в соцсетях:

Взломай свой первый сервер и прокачай скилл — Начни игру на HackerLab

Похожие темы

🚀 Первый раз на Codeby?
Гайд для новичков: что делать в первые 15 минут, ключевые разделы, правила
Начать здесь →
🧭 Навигатор · ИБ 2026
Не знаешь, какой трек твой?
5 направлений ИБ, реальные зарплаты и точка входа для каждого — в одном треде.
JuniorSenior+
100K → 600K+ ₽ /мес
Открыть навигатор →
🔴 Свежие CVE, 0-day и инциденты
То, о чём ChatGPT ещё не знает — обсуждаем в реальном времени
Threat Intel →
💼 Вакансии и заказы в ИБ
Pentest, SOC, DevSecOps, bug bounty — работа и проекты от проверенных компаний
Карьера в ИБ →

HackerLab