В пятницу вечером вы уволили разработчика. Заблокировали учётку в Yandex Cloud. Удалили из организации в VK Cloud. Отчитались перед HR — всё по регламенту. Молодцы.
В понедельник утром объектное хранилище тихо отдаёт терабайт ваших данных.
Никакого взлома. Никакого фишинга. Просто у уволенного был API-ключ сервисного
аккаунта, созданный полгода назад для автоматического деплоя. Ключ жив. Он
никогда не умирает сам по себе. HR об этом не знает. Регламент увольнения
соблюден.
Я занимаюсь информационной безопасностью больше двадцати лет. Эту историю слышал в разных вариациях десятки раз. Каждый раз компании удивляются. Потому что на бумаге всё было сделано правильно. А у уволенного сотрудника доступ к авторизованной когда-то ранее сессии в Контур.Толк еще остался.
Сначала — история, которую вы уже знаете
В 2011 году Бенджамин Делпи выпустил Mimikatz. Инструмент умеет вытаскивать NTLM-хеш пользователя из памяти процесса lsass.exe. Хеш не пароль. Но для протокола NTLM разницы нет: атакующий предъявляет хеш напрямую и ходит по домену без брутфорса, без словарей, без следов взлома. Pass-the-Hash. MITRE ATT&CK T1550.002. Работает до сих пор.
Теперь смотрите на соответствие. AWS-совместимый API-ключ в Yandex Cloud или VK Cloud — это тот же NTLM-хеш, только для облака. Вы его создали, положили в конфиг CI/CD или переменную окружения, и забыли. Атакующий нашёл и ходит по вашей инфраструктуре. Без пароля. Без MFA. Без следов взлома в привычных логах SIEM.
Есть нюанс, который часто путают. NTLM-хеш — производное от пароля, эквивалент пароля. IAM-токен в Yandex Cloud, который живёт 12 часов, — аналог Kerberos Ticket, выданная сессия. Статический API-ключ опаснее обоих: он не протухает, не зависит от активной сессии пользователя и работает из любой точки планеты через обычный HTTPS.
В Active Directory скомпрометированный хеш работал внутри периметра домена. API-ключ российского облака работает из Берлина, Дубая и Бангкока одинаково хорошо. Это качественный скачок в радиусе поражения.
Реальный пример: Snowflake, 165 жертв, 2024 год
В мае 2024 года группа ShinyHunters получила доступ к аккаунтам 165 компаний в облачном хранилище Snowflake. Среди жертв: Ticketmaster (560 миллионов записей покупателей), банк Santander (30 миллионов клиентских аккаунтов), телеком-гигант AT&T.
Компания Mandiant расследовала инцидент. Вывод оказался неудобным: никакой уязвимости в самом Snowflake не было. Все пострадавшие аккаунты работали без многофакторной аутентификации. Учётные данные были украдены инфостилерами у сотрудников и подрядчиков — в ряде случаев эти данные не менялись несколько лет. Группировка UNC5537 просто взяла то, что давно утекло, и авторизовалась.
Это не взлом в привычном смысле. Это авторизованный вход с чужими реквизитами. Именно такую картину SIEM показывает как «норму».
Вывод: неважно, насколько хорошо защищена ваша облачная платформа, если долгоживущие ключи и учётные данные не ротируются и не отзываются при увольнении. В российских облаках та же природа угрозы. Просто у нас об инцидентах с забытыми ключами публично не сообщают. Это не означает, что их нет.
Главная болезнь: «сиротские» ключи
В облаке у API-ключа обычно нет поля «Владелец». Есть поле «Создатель» — технический атрибут, дата и ID сервисного аккаунта. Когда IAM-инженер выгружает список из 500 ключей, он не видит, кто это создал, зачем и что сломается при удалении.
Именно поэтому ключи боятся удалять. «А вдруг упадёт деплой в продакшне?» Так появляются «сиротские» ключи: технически живые, практически бесхозные, потенциально опасные.
При увольнении сотрудника его корпоративная учётка блокируется. Но разработчик мог создать сервисный аккаунт в любой папке, где у него были права. После увольнения его личный доступ к папке закрывается, а сам сервисный аккаунт и его ключи продолжают жить. Никакой автоматической связи между «уволен человек» и «заблокированы его ключи» нет ни в одном российском облаке по умолчанию.
Три истории, которые вы узнаете
История первая. Забытый скрипт. Лид DevOps уволился по-хорошему, без конфликтов. Через полгода финансовый отдел заметил аномальный счёт за исходящий трафик. Расследование показало: его API-ключ работал в скрипте, который каждое воскресенье зеркалировал базу транзакций во внешнее хранилище. Скрипт никто не трогал — он просто работал. Ключ никто не отзывал — он просто жил. Обнаружили только по счёту. Сколько воскресений прошло до обнаружения — посчитайте сами.
История вторая. Публичный снапшот. Разработчик сделал публичный образ
диска в облаке, чтобы передать коллеге тестовую среду. Забыл, что в образе
лежит файл .aws/credentials с ключами доступа к объектному
хранилищу. После его увольнения образ остался публичным. Боты-сканеры,
которые непрерывно индексируют публичные облачные ресурсы, нашли ключи через
два часа. Такие инструменты работают в реальном времени, и подобные инциденты
фиксируются постоянно.
История третья. Матрёшка Terraform. Terraform хранит состояние
инфраструктуры в файле terraform.tfstate. Этот файл обычно лежит
в S3-совместимом объектном хранилище — в том же бакете, доступ к которому
прописан в коде проекта. В самом файле в открытом виде лежат все секреты,
которые Terraform когда-либо передавал разворачиваемым сервисам: пароли баз
данных, ключи API, токены. Один забытый ключ к этому бакету открывает всё.
Здесь есть ещё один конфликт интересов, который часто игнорируют: доступ к состоянию инфраструктуры и право на изменение инфраструктуры — принципиально разные уровни привилегий. На практике они часто достаются одному человеку. Когда он уходит, об этом разграничении никто не вспоминает.
Российские облака: что я нашёл в документации
Yandex Cloud. Документация прямо говорит: IAM-токены живут 12 часов. Разумно. Но API-ключи, авторизованные ключи и статические ключи, совместимые с AWS API, не имеют срока действия. Вендор рекомендует ротацию раз в 90 дней по стандарту PCI DSS. Рекомендует, не требует. Принудительного TTL нет. Я не видел ни одной российской организации, у которой была бы автоматизированная ротация статических ключей Yandex Cloud.
VK Cloud. В октябре 2024 года запущен Cloud Audit — мониторинг событий безопасности в реальном времени. Полезный инструмент. Автоматического отзыва API-ключей при деактивации пользователя-создателя в публичной документации нет. Рекомендация простая: запросите у службы поддержки письменно — «Что происходит с ключами сервисных аккаунтов при блокировке пользователя?» Ответ зафиксируйте в регламентах. Если вендор не описывает поведение системы при увольнении сотрудника, вы не можете на это поведение полагаться.
Selectel. Один из старейших российских провайдеров с большой базой клиентов на классических API-ключах. Ключи создаются на уровне проекта, и после увольнения сотрудника связь «чей это ключ» теряется быстро: проект продолжает жить, ключи продолжают работать.
MTS Web Services. Активно развивает гранулярный IAM. Если ваша организация использует интеграцию с внешним IdP через SAML или AD FS, проверьте задержку синхронизации групп. Синхронизация с задержкой в несколько часов превращает окно между увольнением и реальной блокировкой доступа в открытую дверь.
Cloud.ru. Документация по управлению жизненным циклом ключей в открытом доступе минимальна. Это само по себе риск: если вендор не описывает поведение системы при отзыве доступа, строить на этом регламенты нельзя.
Конфликт IAM и SOC, о котором не принято говорить
В большинстве компаний IAM и SOC живут отдельно и разговаривают редко. IAM считает своей задачей выдать доступ. SOC считает, что IAM отвечает за идентичность. В результате никто не отвечает за жизненный цикл ключа после того, как его создатель уволился.
IAM-инженер создал ключ — его задача выполнена. SOC мониторит события — легитимный API-вызов с корректным ключом не триггерит алерт. Процесс мёртв. Ключ жив.
Большинство компаний измеряет Mean Time to Detect — время обнаружения атаки. Почти никто не измеряет другое: сколько времени инфраструктура продолжает доверять уже уволенному человеку через его забытые ключи. Первая метрика говорит, как быстро вы увидели проблему. Вторая — как долго проблема работала после того, как вы её увидели.
Исправляется это организационно. Введите роль Token Lifecycle Owner. Обычно это IAM-архитектор, но отчитывается он перед CISO. Его задача: раз в квартал инвентаризировать ключи, сверять создателей с HR-списком уволенных, удалять осиротевшие. Внесите в регламент увольнения отдельный пункт: «Сотрудник ИБ проверяет и документирует факт отзыва всех API-ключей сервисных аккаунтов, которыми пользовался уволенный. Без подписи — процедура не закрыта».
И один юридический момент, который дисциплинирует даже добросовестных людей. В соглашении о расторжении или в NDA пропишите явно: использование технических доступов после даты увольнения квалифицируется как неправомерный доступ к компьютерной информации по статье 272 УК РФ. Это не угроза — это напоминание. Человек, который «просто оставил скрипт работать», должен понимать юридические последствия.
Что сделать в понедельник до обеда
Yandex Cloud — инвентаризация через CLI. Команды работают для одного сервисного аккаунта; для полного охвата папки повторите для каждого SA из списка или используйте цикл в bash:
# Список всех сервисных аккаунтов в папке yc iam service-account list --folder-id <folder-id> # API-ключи конкретного сервисного аккаунта yc iam api-key list --service-account-id <sa-id> # Авторизованные ключи yc iam key list --service-account-id <sa-id>
Выгрузите результат. Найдите ключи старше 90 дней. Сверьте создателей с HR-списком уволенных за этот период. Ключи, которые боитесь удалять — сначала проверьте: если сервис работает без ключа, он давно не используется.
Тест скорости отзыва. Создайте тестовый сервисный аккаунт и
сгенерируйте именно API-ключ командой yc iam api-key create, не
авторизованный ключ — это разные объекты с разным кешированием. Выполните
тестовый запрос, убедитесь, что он проходит. Удалите ключ в консоли. Засеките
время до появления ошибки 403 при повторном запросе. У ряда провайдеров
кеширование даёт до 15 минут задержки. Это ваше окно атаки — зафиксируйте
цифру для руководства.
VK Cloud. Включите Cloud Audit. Настройте нотификацию на событие создания нового API-ключа. Любой новый ключ должен попадать в SIEM или хотя бы на почту IAM-команды. Это 20 минут работы.
SOC. Добавьте правило: массовое скачивание из объектного хранилища от сервисного аккаунта, нетипичное для его исторического поведения — триггер для расследования. Не ждите алерта на «подозрительный IP». Смотрите на аномалию внутри сессии.
GitHub-репозитории уволенных. Попросите HR включить в чек-лист увольнения пункт: проверить публичные репозитории сотрудника на GitHub и GitLab за последние 30 дней активности. Люди, которые уходят и хотят «сохранить наработки», часто в последние дни пушат конфиги со всем, что там лежало. Инструменты типа truffleHog и gitleaks автоматизируют поиск секретов в публичных репозиториях по имени пользователя.
Terraform-бакеты. Проверьте, кто имеет доступ к бакету с файлами
terraform.tfstate. Права на чтение этого файла и права на
изменение инфраструктуры — это разные уровни привилегий, которые не должны
принадлежать одному человеку и уж точно не должны оставаться у уволенного.
Почему автоматическую ротацию нужно строить сейчас
Количество сервисных аккаунтов в инфраструктуре растёт само по себе. Каждый новый CI/CD пайплайн, каждая межсервисная интеграция, каждый микросервис требует своих ключей. Через год их будет в три раза больше, чем сейчас. Ручная квартальная инвентаризация перестанет работать физически.
HashiCorp Vault или облачный Secret Manager с коротким TTL решают проблему архитектурно: ключ живёт 24 часа, ротируется автоматически, никогда не попадает в Git и не задерживается в памяти CI/CD дольше нужного. Если этого нет сейчас — внесите в roadmap на ближайший квартал. Иначе через год вы будете проводить инвентаризацию тысячи ключей вместо сотни.
Новые метрики, которых нет на вашем дашборде
Старые KPI придуманы под периметровую защиту. Для работы с облачными ключами нужны другие.
Percentage of Non-Rotated Keys — доля ключей без ротации более 90 дней. Orphaned Key Count — ключи, чьи создатели уволились. Dormant Service Account Exposure — сервисные аккаунты, неактивные более 30 дней, с живыми ключами. Time to Key Revocation — время от блокировки пользователя до удаления его ключей. tfstate Exposure Rate — процент Terraform-бакетов с широким или публичным доступом.
Если ни одна из этих метрик не измеряется — вы не знаете реального состояния своей облачной идентичности.
Итог
Pass-the-Hash двадцать лет назад показал простую вещь: не нужно знать пароль, если у тебя есть то, чему система доверяет так же, как паролю. API-ключ без срока жизни — та же история. Другой протокол, другой интерфейс, тот же принцип.
Snowflake потерял данные 165 компаний не потому что был взломан. Потому что учётные данные клиентов годами не менялись. В российских облаках та же картина — только публичных отчётов об инцидентах нет. Это не означает, что инцидентов нет.
Сделайте один тест прямо сейчас. Выгрузите список API-ключей вашей инфраструктуры и найдите те, чьи создатели уже не работают в компании. Напишите в комментариях одну цифру — сколько таких ключей нашлось. Именно это удивление — лучший аргумент для разговора с руководством о Token Lifecycle Owner и о том, что ваша процедура увольнения закрывает человека, но не его следы.