Автоматизирана кампания използва откраднати GitHub токени за внедряване на работни процеси (workflows), които извеждат тайните (secrets) на хранилището в неговите логове на GitHub Actions, след което атакуващите ги изтеглят, преди да изтрият изпълненията на задачите. Атаките са били успешни в частни хранилища и среди на GitHub Enterprise според анализ на компанията за облачна сигурност Wiz.
Защитна мярка на GitHub, която поставя на пауза подозрителни изпълнения на работни процеси, е спряла всяко изпълнение в публично хранилище, проверено от Wiz, но тя не обхваща частните хранилища или GitHub Enterprise Server.
Всеки работен процес се намира в нов клон, именуван с ci-sync-, последвано от шест произволни знака. Изтриването на клон или на стартираното от него изпълнение не премахва компрометирането. Всяка тайна, до която хранилището е имало достъп за четене, трябва да бъде сменена (ротирана), а токенът, чрез който е качен клонът — анулиран.
Wiz проследява кампанията от 15 септември и я нарича Gheist по името на потребителския агент (user agent) gheist, който инструментът на атакуващите изпраща със заявките към GitHub API.
Wiz е възстановила повече от 13 500 внедрени клона от над 850 компрометирани акаунта — от лични проекти до частни хранилища на корпоративни организации. Анализът на Wiz не посочва колко организации са с компрометирани тайни.
В частните хранилища и в GitHub Enterprise Server одитните логове на GitHub показват как изпълненията на внедрените клонове приключват и след това се изтриват от потребителския агент gheist. Логовете на AWS CloudTrail показват, че собствените работни процеси на организацията също работят по тези клонове и поемат роли в AWS — признак, че GitHub Actions е работил там без одобрение.
В корпоративните организации инструментът е редувал токени от няколко потребители и акаунти за автоматизация в рамките на минути и е клонирал частни хранилища, преди да внедри работния процес. Часове по-късно облачни идентификационни данни от същата организация са били използвани за изброяване (enumeration) в AWS Secrets Manager. Анализът на Wiz не посочва откъде са дошли тези идентификационни данни или кой ги е използвал.
Към 24 октомври кампанията все още е активна и търпи промени. Около две трети от засегнатите акаунти вече не са били достъпни в GitHub. Wiz е докладвала дейността на GitHub и посочва, че тяхното изчезване вероятно отразява предприети мерки.
Всеки, който има права за запис в GitHub хранилище, може да прочете всяка конфигурирана в него тайна според документацията на GitHub. Откраднат токен с такива права е напълно достатъчен.
За всяко хранилище, до което даден токен има достъп, инструментът създава клон ci-sync- и записва (commit) един файл — .github/workflows/sync-check.yml със съобщение ci: sync config. Записът не е подписан и включва името на собственика на токена; изпращането му (push) стартира работния процес.
Работният процес извежда средата на задачата и всяка тайна, до която тя има достъп за четене, кодирани в base32. GitHub маскира тайните в логовете, но в документацията му се посочва, че това не е гарантирано, след като дадена стойност е била кодирана или променена по друг начин. Wiz заявява, че base32 текстът вече не съвпада с оригиналната тайна, поради което тя се отпечатва изцяло.
Работният процес задава празен блок с разрешения. Това ограничава токена GITHUB_TOKEN за задачата, който не е необходим на атакуващите, и не пречи на задачата да чете тайните.
Една от версиите на инструмента стартира и задача за всяка среда за внедряване (deployment environment) в хранилището, така че тайните, ограничени до тези среди, също се отпечатват. Според Wiz това често са производствени идентификационни данни.
След това инструментът изтегля лога чрез API на GitHub и изтрива изпълнението секунди по-късно. Тъй като тайните излизат директно през самия GitHub, няма сървър на атакуващите или изходяща връзка, които да бъдат блокирани.
От 28 юли GitHub задържа изпълненията на работни процеси, които определя като потенциално злонамерени, докато сътрудник с права за запис не ги одобри. От GitHub посочват, че задържането „понастоящем се прилага само за публични хранилища в github.com“ и че към момента GitHub Enterprise Server не разполага с тази функция.
Всяко публично изпълнение на Gheist, проверено от Wiz във всички версии на инструмента, все още е очаквало одобрение, така че неговият зловреден код никога не е бил стартиран.
Задържането улавя само изпълнения, които GitHub маркира като съмнителни. Нов вариант на GhostAction, отделна кампания, се е изпълнявал в публични хранилища, докато GitHub не започна да го блокира на 9 октомври според проучване на компанията за сигурност GitGuardian. Wiz заявява, че Gheist се различава от GhostAction, която използва различни файлове за работни процеси.
Около 19 октомври една от версиите на инструмента е започнала да качва втора задача, предназначена за самостоятелно хоствани изпълнители (self-hosted runners) — машините, които организациите управляват сами, за да обработват задачи на GitHub Actions. Изглежда, че тя е насочена само към хранилища, в които има регистриран такъв изпълнител.
Задачата е създадена да търси в машината на изпълнителя идентификационни данни, включително 31 типа токени: частни ключове, променливи на средата на процесите, идентификационни данни за роли на AWS инстанции, конфигурационни файлове на изпълнителя и токена на сервизния акаунт в Kubernetes. Wiz описва задачата като съдържаща грешки и анализът й не отчита нито едно успешно изпълнение.
Източниците, които Wiz успява да проследи за откраднатите токени, включват логове от зловреден софтуер за кражба на данни (infostealers) и токени, компрометирани при по-ранни атаки по веригата за доставки, като например компрометирането на скенера за уязвимости Trivy през март.
Други атакуващи също използват същите акаунти. На 6 октомври 391 акаунта, много от които са използвани и от Gheist, преименуват около 1461 хранилища, за да изглеждат като кракнат софтуер и да разпространяват зловреден софтуер. Преименуването заличава 610 от внедрените клонове.
Някои от жертвите също така изглежда са заразени с PolinRider — зловреден софтуер, който изследователите свързват със Северна Корея. На 19 и 20 октомври трима от тях са качили повторно своите Gheist записи с добавен зареждащ модул (loader) във файл vite.config.js.
Megalodon — кампания, която през май внедри работни процеси за кражба на тайни в хиляди хранилища на GitHub — също е засегнала 57 от тези акаунти.
Как да проверите вашите хранилища
- Търсете клонове с име
ci-sync-, последвано от шест знака, където единствената промяна е нов файл.github/workflows/sync-check.ymlсъс съобщение за записci: sync config. - В одитните логове на GitHub търсете изпълнения на работни процеси по клонове
ci-sync-*, които са били изтрити в рамките на минута след приключването им, както и всякаква активност от потребителския агентgheist. - Ако вашите работни процеси се вписват в облачен доставчик чрез OIDC, проверете одитните логове на облачната среда за поемане на роли или обмен на токени, чийто субект (subject) включва клон
ci-sync-. Това работи дори и ако не събирате логове от GitHub. - При самостоятелно хоствани изпълнители (self-hosted runners) търсете файловете
.gdmp_pat,.gdmp_patgи.gdmp_sweep, както и низаgdmp-pivotв логовете на задачите.
OIDC позволява на работните процеси да се вписват с краткотрайни токени вместо със съхранявани облачни ключове. По подразбиране субектът на токена включва името на клона само когато задачата не използва среда за внедряване според документацията за OIDC на GitHub.
- Потребителски агент:
gheist - Клон:
^ci-sync-[0-9a-z]{6}$ - Съобщение при качване на код (commit message):
ci: sync config, добавящо единствено.github/workflows/sync-check.yml - Низ:
toJSON(secrets) }}' | base32 -w 120 - Низ:
===== gdmp-pivot: - Файл:
.gdmp_pat - Файл:
.gdmp_patg - Файл:
.gdmp_sweep - Git blob SHA (обикновен работен процес):
f3da2b8b357dcda02fd455d314be2a95007516a6 - Git blob SHA (версия с изтичане на времето):
d09535857a741bbb976bdc084a9a021713133291 - Git blob SHA (версия с разделител):
1dc5af9cce950aad1eb1546ecce8565b117540c4 - Git blob SHA (версия със собствено хоствана задача):
c665b778b2d822453293003e7ca0bbb2cb08e39d
Версиите на работния процес, които изброяват средите за внедряване на дадено хранилище, варират в зависимост от хранилището, така че те нямат фиксиран хеш.
Какво да направите, ако откриете клон ci-sync
Wiz препоръчва следните стъпки за засегнато хранилище:
- Ротирайте всяка тайна на ниво хранилище, организация и среда, която хранилището би могло да използва.
- Анулирайте токените, чрез които са качени промените (commit-нати), и проверете устройствата на техните собственици за инфостийлъри (софтуер за кражба на данни).
- Ако клон от тип ci-sync се е изпълнил на собствено хостван агент (self-hosted runner), третирайте машината и нейната роля в облачната инстанция като компрометирани.
- Не одобрявайте задържани изпълнения на sync-check и не стартирайте код от ci-sync клонове.
За да се намали полезността на откраднат токен, Wiz също така препоръчва следните стъпки:
- Изисквайте проверяващи лица (reviewers) за среди, които съдържат производствени тайни.
- Ограничете политиките за доверие на OIDC само до защитени клонове или среди.
- Използвайте GitHub Apps или краткотрайни токени с прецизно зададени права (fine-grained tokens) вместо лични токени за достъп (PAT).
- Стартирайте собствено хостваните агенти (self-hosted runners) като краткотрайни машини без достъп до сокета на Docker или свободен достъп до облачните метаданни.
Дадена задача не може да чете тайните на дадена среда, докато изискуем проверяващ не я одобри, според документацията на GitHub.