Gheist крадёт секреты приватных GitHub-репозиториев через логи Actions

Кампания Gheist использует похищенные токены GitHub для создания вредоносных workflow и вывода секретов репозиториев в журналы GitHub Actions. Компания Wiz отследила более 13 500 созданных веток в более чем 850 скомпрометированных аккаунтах; атаки затронули как личные проекты, так и приватные репозитории организаций и среды GitHub Enterprise.
Ветка получает имя по шаблону ci-sync- и шесть случайных символов. В неё добавляется единственный файл .github/workflows/sync-check.yml с сообщением коммита ci: sync config. Публикация коммита запускает workflow от имени владельца украденного токена.
Как секреты попадают в журналы
Workflow выводит окружение задания и все секреты, доступные заданию, предварительно кодируя значения в base32. GitHub маскирует секреты в логах, однако документация платформы предупреждает, что защита не гарантирована, если значение было преобразовано. По оценке Wiz, кодированная строка не совпадает с исходным секретом и поэтому публикуется полностью.
После выполнения инструмент скачивает журнал через GitHub API и удаляет запуск спустя несколько секунд. При такой схеме секреты покидают репозиторий через сам GitHub: отдельного сервера атакующих или исходящего соединения, которое можно было бы заблокировать на периметре, не требуется.
Пустой блок permissions в workflow ограничивает встроенный GITHUB_TOKEN, но не мешает заданию читать секреты, к которым оно имеет доступ. Один из вариантов инструмента также перебирает deployment environments, чтобы получить секреты, привязанные к окружениям. Wiz отмечает, что среди них нередко оказываются учётные данные production-систем.
Почему приватные репозитории под особым риском
С 28 июля GitHub удерживает подозрительные запуски workflow до одобрения пользователя с правом записи, но механизм действует только для публичных репозиториев на github.com. Все публичные запуски Gheist, проверенные Wiz, ожидали одобрения и не выполнили полезную нагрузку. На приватные репозитории и GitHub Enterprise Server эта защита не распространяется.
В аудит-логах приватных репозиториев и GitHub Enterprise Server Wiz увидела завершённые и затем удалённые запуски на ветках ci-sync-. В AWS CloudTrail фиксировались запуски штатных workflow организации на этих ветках и получение AWS-ролей, что указывает на выполнение GitHub Actions без отдельного согласования.
Примерно с 19 октября один вариант инструмента начал добавлять задание для self-hosted runners. Оно ищет на машине ключи, переменные окружения, учётные данные AWS instance role, файлы раннера и токен service account Kubernetes. Wiz называет код ошибочным и не сообщает об успешных запусках, однако сам факт появления такого задания требует отдельной проверки собственных раннеров.
Что проверить и как реагировать
Wiz рекомендует искать ветки по шаблону ^ci-sync-[0-9a-z]{6}$, где единственным изменением является sync-check.yml, а сообщение коммита — ci: sync config. В GitHub audit logs стоит проверить запуски на таких ветках, удалённые менее чем через минуту после завершения, а также запросы с user agent gheist.
Организациям, использующим OIDC для доступа workflow к облаку, следует просмотреть облачные аудит-логи на получение ролей или обмен токенов, в subject которых указана ветка ci-sync-. На self-hosted runners индикаторами служат файлы .gdmp_pat, .gdmp_patg, .gdmp_sweep и строка gdmp-pivot в журналах заданий.
При обнаружении ветки ci-sync- необходимо отозвать токены, которыми был отправлен коммит, и сменить все секреты репозитория, организации и окружений, доступные этому репозиторию. Если workflow запускался на self-hosted runner, Wiz советует считать скомпрометированными и саму машину, и её облачную instance role. Практический вывод для бизнеса: контроль веток и запусков Actions должен дополняться короткоживущими токенами, ограничением OIDC доверия защищёнными ветками и обязательным одобрением для окружений с production-секретами.

