На аудите 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 деплоя
Анатомия CVE-2026-33757: OIDC callback без подтверждения пользователя
Уязвимость классифицирована как 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:N | Network | Атака через сеть - физический доступ не нужен |
| AC:L | Low | Нет специальных условий, кроме наличия роли с direct mode |
| PR:N | None | Любой может инициировать OIDC auth request, привилегии не требуются |
| UI:R | Required | Жертва должна кликнуть по ссылке и аутентифицироваться в IDP |
| S:C | Changed | Через украденные секреты атакуются другие системы за пределами OpenBao |
| C:H | High | Полный доступ к секретам в рамках политик жертвы |
| I:H | High | Модификация секретов при наличии write-политик |
| A:L | Low | Минимальное влияние на доступность самого 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
Штатный OIDC flow (стандартный callback):
- Пользователь запрашивает вход в OpenBao через CLI или UI
- OpenBao генерирует auth URL с параметрами
state,nonce,redirect_uri - Браузер пользователя перенаправляется в IDP (Keycloak, Okta, Azure AD)
- Пользователь аутентифицируется в IDP
- IDP возвращает authorization code в браузер пользователя через redirect
- Браузер пользователя отправляет code обратно в OpenBao
- OpenBao обменивает code на ID token, проверяет
state/nonce, выдаёт vault token - Vault token получает пользователь, инициировавший flow
- Атакующий инициирует auth request к API, получает auth URL с
stateиnonce - Атакующий отправляет auth URL жертве (фишинг, мессенджер, email)
- Жертва кликает, аутентифицируется в IDP
- IDP возвращает authorization code напрямую в API OpenBao, а не в браузер жертвы
- OpenBao привязывает vault token к сессии, инициированной атакующим
- Атакующий поллит API и получает vault token жертвы
Шаг 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
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"
Шаг 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
Место в цепочке атаки
CVE-2026-33757 сидит между initial access и credential access:- Recon - обнаружение OpenBao инстанса, fingerprinting OIDC-ролей с
callback_mode=direct - Initial Access (T1190) - эксплуатация уязвимого OIDC flow через фишинг
- Credential Access (T1539) - получение vault token с правами жертвы
- Privilege Escalation - если политики жертвы включают admin-уровень, атакующий получает полный контроль над secrets engine
- Lateral Movement (T1550.004) - credentials из secrets engine (database passwords, API keys, SSH keys) открывают доступ к другим системам
- Exfiltration - массовое чтение секретов через vault API
Детектирование через аудит-логи 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 | Да - полностью | Требует тестирования в staging | 1-4 часа |
| Удаление callback_mode=direct | Да - полностью | Ломает automated auth flows, зависящие от direct mode | 15 минут |
| 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-запросов
- Сеть: локальная, интернет не нужен после скачивания образов
- Поднять OpenBao в dev-режиме:
docker run -d --name openbao -p 8200:8200 openbao/openbao server -dev. Dev-режим автоматически unseal'ит vault и выдаёт root token в stdout - Поднять 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 - Настроить в Keycloak: создать realm, OIDC client с redirect URI на callback endpoint OpenBao, тестового пользователя
- Сконфигурировать OIDC auth method в OpenBao: включить
auth/oidc, создать роль сcallback_mode=direct, указатьoidc_discovery_urlот Keycloak, привязатьtoken_policies - Открыть Burp Suite, настроить proxy для перехвата запросов к OpenBao API на порту 8200
- В терминале (имитация атакующего) выполнить GET-запрос на
/v1/auth/oidc/oidc/auth_urlс нужной ролью, сохранитьstateиnonceиз ответа - В другом браузере (имитация жертвы) перейти по полученному auth URL, аутентифицироваться в Keycloak
- Наблюдать в Burp: callback приходит в API, token выдаётся в сессию «атакующего»
- Проверить доступ: использовать полученный token для
bao kv get
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.
Последнее редактирование: