Avtomatlashtirilgan kampaniya o'g'irlangan GitHub tokenlaridan foydalanib, repozitoriy sirlarini GitHub Actions loglariga chop etadigan ish oqimlarini joylashtirmoqda, so'ngra hujumchilar ishga tushirishlarni o'chirishdan oldin ularni yuklab olishadi. Bulut xavfsizligi kompaniyasi Wiz tahliliga ko'ra, hujumlar shaxsiy repozitoriylarda va GitHub Enterprise muhitlarida muvaffaqiyatli bo'lgan.
Shubhali ish oqimi ishga tushirishlarini to'xtatadigan GitHub himoyasi Wiz tekshirgan har bir ommaviy repozitoriya ishga tushirishini to'xtatdi, ammo u shaxsiy repozitoriyalar yoki GitHub Enterprise Serverni qamrab olmaydi.
Har bir ish oqimi ci-sync- va olti tasodifiy belgidan iborat yangi tarmoqda joylashadi. Tarmoqni yoki u boshlagan ishga tushirishni o'chirish ta'sirni bekor qilmaydi. Repozitoriya o'qishi mumkin bo'lgan har bir sir aylantirilishi va tarmoqni surgan token bekor qilinishi kerak.
Wiz kampaniyani 15-sentabrdan kuzatib kelmoqda va uni hujumchilarning vositasi GitHub API so'rovlarida yuboradigan gheist foydalanuvchi agenti nomi bilan Gheist deb ataydi.
Wiz 850 dan ortiq buzilgan hisobdan 13 500 dan ortiq joylashtirilgan tarmoqni tiklagan — shaxsiy loyihalardan tortib korporativ tashkilotlarning shaxsiy repozitoriyalarigacha. Wiz tahlili nechta tashkilot sirlarini fosh qilganini aytmaydi.
Shaxsiy repozitoriylarda va GitHub Enterprise Serverda GitHub audit loglari joylashtirilgan tarmoqlarda ishga tushirishlar tugallanganini va keyin gheist foydalanuvchi agenti tomonidan o'chirilganini ko'rsatadi. AWS CloudTrail loglari tashkilotning o'z ish oqimlari ham o'sha tarmoqlarda ishlaganini va AWS rollarini qabul qilganini ko'rsatadi — bu GitHub Actions u yerda tasdiqlanmasdan ishlaganining belgisi.
Korporativ tashkilotlarda vosita bir necha foydalanuvchi va avtomatlashtirish hisoblarining tokenlari orqali bir necha daqiqa ichida aylangan va shaxsiy repozitoriyalarni klonlagan, so'ngra ish oqimini joylashtirgan. Bir necha soat o'tgach, o'sha tashkilotdan bulut ma'lumotlari AWS Secrets Managerni tekshirish uchun ishlatilgan. Wiz tahlili bu ma'lumotlar qayerdan kelganini yoki ularni kim ishlatganini aytmaydi.
24-oktabr holatiga ko'ra, kampaniya hali ham ishlamoqda va o'zgarib bormoqda. Ishtirok etgan hisoblarning taxminan uchdan ikki qismi GitHubda endi mavjud emas. Wiz faoliyatni GitHubga xabar qilgan va ularning yo'qolishi ehtimol javobni aks ettiradi, deydi.
GitHub hujjatlariga ko'ra, GitHub repozitoriyasiga yozish huquqiga ega har kim unda sozlangan har bir sirni o'qishi mumkin. Bunday kirish huquqiga ega o'g'irlangan token yetarli.
Token yetadigan har bir repozitoriya uchun vosita ci-sync- tarmog'ini yaratadi va bitta faylni, .github/workflows/sync-check.yml ni, ci: sync config xabari bilan joylashtiradi. Kommit imzolanmagan va token egasining nomini o'z ichiga oladi; uni surish ish oqimini boshlaydi.
Ish oqimi ish muhitini va ish o'qishi mumkin bo'lgan har bir sirni base32 bilan kodlangan holda chop etadi. GitHub loglarda sirlarni yashiradi, ammo uning hujjatlarida aytilishicha, qiymat kodlangan yoki boshqa tarzda o'zgartirilganidan keyin bu kafolatlanmaydi. Wiz aytishicha, base32 matni endi asl sirga mos kelmaydi, shuning uchun u to'liq chop etiladi.
Ish oqimi bo'sh ruxsatlar blokini o'rnatadi. Bu ishning GITHUB_TOKEN ini cheklaydi, hujumchilarga kerak emas, va ish sirlarni o'qishdan to'xtamaydi.
Vositaning bir versiyasi repozitoriydagi har bir joylashtirish muhiti uchun ham ishni ishga tushiradi, shuning uchun o'sha muhitlarga cheklangan sirlar ham chop etiladi. Wiz aytishicha, bular ko'pincha ishlab chiqarish ma'lumotlari.
So'ngra vosita logni GitHub API orqali yuklab oladi va bir necha soniya o'tgach ishga tushirishni o'chiradi. Sirlar GitHubning o'zi orqali chiqib ketgani uchun, hujumchi serveri yoki bloklanadigan tashqi ulanish yo'q.
28-iyuldan beri GitHub potentsial zararli deb aniqlagan ish oqimi ishga tushirishlarini yozish huquqiga ega hamkor tasdiqlaguncha ushlab turadi. GitHub aytishicha, bu ushlab turish "hozirda faqat github.com dagi ommaviy repozitoriyalarga tegishli" va GitHub Enterprise Server hozircha buni qo'llab-quvvatlamaydi.
Wiz tekshirgan har bir ommaviy Gheist ishga tushirishi, vositaning barcha versiyalarida, hali ham tasdiqlashni kutmoqda, shuning uchun uning yuklamasi hech qachon ishlamagan.
Ushlab turish faqat GitHub belgilagan ishga tushirishlarni ushlaydi. GitGuardian xavfsizlik kompaniyasi tadqiqotiga ko'ra, alohida kampaniya GhostActionning yangi varianti GitHub 9-oktabrda uni bloklashni boshlaguncha ommaviy repozitoriylarda ishlagan. Wiz aytishicha, Gheist GhostActiondan farq qiladi, u turli ish oqimi fayllaridan foydalanadi.
19-oktabr atrofida vositaning bir versiyasi o'z-o'zini boshqaradigan ishchilar, ya'ni tashkilotlar GitHub Actions ishlarini qayta ishlash uchun o'zlari ishlatadigan mashinalar uchun mo'ljallangan ikkinchi ishni surishni boshlagan. U faqat bunday ishchi ro'yxatdan o'tgan repozitoriyalarga qaratilganga o'xshaydi.
Ish ishchi mashinasida ma'lumotlarni qidirish uchun yozilgan, jumladan 31 turdagi tokenlar: shaxsiy kalitlar, jarayon muhitlari, AWS misol roli ma'lumotlari, ishchi ma'lumot fayllari va Kubernetes xizmat hisobi tokeni. Wiz bu ishni xato deb ta'riflaydi va uning tahlili muvaffaqiyatli ishga tushirishni xabar qilmaydi.
Wiz kuzatgan o'g'irlangan tokenlar manbalari infostealer loglari va oldingi ta'minot zanjiri hujumlarida fosh qilingan tokenlarni o'z ichiga oladi, masalan, mart oyida Trivy zaiflik skaneri buzilishi.
Boshqa hujumchilar ham o'sha hisoblardan foydalanadi. 6-oktabrda 391 ta hisob, ularning ko'pchiligi Gheist tomonidan ham ishlatilgan, taxminan 1 461 ta repozitoriyani buzilgan dasturiy ta'minotga o'xshatish va zararli dastur tarqatish uchun nomini o'zgartirgan. Nom o'zgartirish 610 ta joylashtirilgan tarmoqni o'chirgan.
Ba'zi jabrlanuvchilar ham Shimoliy Koreya bilan bog'langan PolinRider zararli dasturi bilan zararlangan ko'rinadi. 19 va 20-oktabrda ularning uchtasi o'zlarining Gheist kommitlarini vite.config.js fayliga yuklovchi qo'shilgan holda qayta surgan.
May oyida minglab GitHub repozitoriyalariga sir o'g'irlovchi ish oqimlarini joylashtirgan Megalodon kampaniyasi ham 57 ta hisobni urgan.
Repozitoriylaringizni Qanday Tekshirish Kerak
Wiz quyidagi tekshiruvlarni tavsiya qiladi:
- ci-sync- va olti belgidan iborat tarmoqlarni qidiring, u yerda yagona o'zgarish — ci: sync config xabari bilan yangi .github/workflows/sync-check.yml fayli.
- GitHub audit loglarida tugallanganidan bir daqiqa ichida o'chirilgan ci-sync-* tarmoqlaridagi ish oqimi ishga tushirishlarini va gheist foydalanuvchi agentidan har qanday faoliyatni qidiring.
- Agar ish oqimlaringiz OIDC bilan bulut provayderiga kirsa, bulut audit loglarida mavzusi ci-sync- tarmog'ini o'z ichiga olgan rol qabul qilishlari yoki token almashishlarini tekshiring. Bu hatto GitHub loglarini yig'masangiz ham ishlaydi.
- O'z-o'zini boshqaradigan ishchilarda .gdmppat, .gdmppatg va .gdmp_sweep fayllarini va ish loglarida gdmp-pivot qatorini qidiring.
OIDC ish oqimlariga saqlangan bulut kalitlari o'rniga qisqa muddatli tokenlar bilan kirish imkonini beradi. GitHub OIDC hujjatlariga ko'ra, ish joylashtirish muhitidan foydalanmasa, token mavzusi sukut bo'yicha faqat tarmoq nomini o'z ichiga oladi.
E'lon qilingan indikatorlar:
- Foydalanuvchi agenti: gheist
- Tarmoq: ^ci-sync-[0-9a-z]{6}$
- Kommit xabari: ci: sync config, faqat .github/workflows/sync-check.yml qo'shadi
- Qator: toJSON(secrets) }}' | base32 -w 120
- Qator: ===== gdmp-pivot:
- Fayl: .gdmp_pat
- Fayl: .gdmp_patg
- Fayl: .gdmp_sweep
- Git blob SHA (oddiy ish oqimi): f3da2b8b357dcda02fd455d314be2a95007516a6
- Git blob SHA (vaqt tugashi versiyasi): d09535857a741bbb976bdc084a9a021713133291
- Git blob SHA (ajratgich versiyasi): 1dc5af9cce950aad1eb1546ecce8565b117540c4
- Git blob SHA (o'z-o'zini boshqaradigan ish versiyasi): c665b778b2d822453293003e7ca0bbb2cb08e39d
Repozitoriyaning joylashtirish muhitlarini ro'yxatga oladigan ish oqimi versiyalari repozitoriyaga qarab farq qiladi, shuning uchun ular doimiy hashga ega emas.
Agar ci-sync Tarmog'ini Topsangiz Nima Qilish Kerak
Wiz ta'sirlangan repozitoriya uchun quyidagi qadamlarni tavsiya qiladi:
- Repozitoriya, tashkilot va muhit foydalanishi mumkin bo'lgan har bir sirni aylantiring.
- Kommitlarni surgan tokenlarni bekor qiling va ularning egalarining qurilmalarini infostealerlar uchun tekshiring.
- Agar ci-sync tarmog'i o'z-o'zini boshqaradigan ishchida ishlagan bo'lsa, mashinani va uning bulut misol rolini buzilgan deb hisoblang.
- Ushlab turilgan sync-check ishga tushirishlarini tasdiqlamang va ci-sync tarmoqlaridan kodni ishga tushirmang.
O'g'irlangan tokenni kamroq foydali qilish uchun Wiz quyidagi qadamlarni ham tavsiya qiladi:
- Ishlab chiqarish sirlarini saqlaydigan muhitlarda tekshiruvchilarni talab qiling.
- OIDC ishonch siyosatlarini himoyalangan tarmoqlar yoki muhitlar bilan cheklang.
- Shaxsiy kirish tokenlari o'rniga GitHub Apps yoki qisqa muddatli nozik donali tokenlardan foydalaning.
- O'z-o'zini boshqaradigan ishchilarni Docker soketiga kirishsiz yoki bulut metama'lumotlariga ochiq kirishsiz qisqa muddatli mashinalar sifatida ishga tushiring.
GitHub hujjatlariga ko'ra, ish kerakli tekshiruvchi tasdiqlaguncha muhit sirlarini o'qiy olmaydi.
An automated campaign is using stolen GitHub tokens to plant workflows that print a repository's secrets into its GitHub Actions logs, which the attackers then download before deleting the runs. The attacks have succeeded in private repositories and GitHub Enterprise environments, according to an analysis by cloud security company Wiz.
A GitHub safeguard that pauses suspicious workflow runs stopped every public-repository run Wiz checked, but it does not cover private repositories or GitHub Enterprise Server.
Each workflow sits on a new branch named ci-sync- followed by six random characters. Deleting a branch, or the run it started, does not undo the exposure. Every secret the repository could read should be rotated, and the token that pushed the branch revoked.
Wiz has tracked the campaign since September 15 and calls it Gheist, after the user agent gheist that the attackers' tool sends with GitHub API requests.
Wiz has recovered more than 13,500 planted branches from more than 850 compromised accounts, from personal projects to the private repositories of enterprise organizations. Wiz's analysis does not say how many organizations had secrets exposed.
In private repositories and on GitHub Enterprise Server, GitHub audit logs show runs on the planted branches finishing and then being deleted by the gheist user agent. AWS CloudTrail logs show the organization's own workflows also running on those branches and assuming AWS roles, a sign that GitHub Actions ran there without approval.
In enterprise organizations, the tool cycled through tokens from several users and automation accounts within minutes and cloned private repositories before planting the workflow. Hours later, cloud credentials from the same organization were used to enumerate AWS Secrets Manager. Wiz's analysis does not say where those credentials came from or who used them.
As of October 24, the campaign was still running and changing. About two-thirds of the accounts involved were no longer available on GitHub. Wiz reported the activity to GitHub and says their disappearance likely reflects a response.
Anyone with write access to a GitHub repository can read every secret configured in it, according to GitHub's documentation. A stolen token with that access is enough.
For each repository a token can reach, the tool creates a ci-sync- branch and commits one file, .github/workflows/sync-check.yml, with the message ci: sync config. The commit is unsigned and includes the token owner's name; pushing it starts the workflow.
The workflow prints the job's environment and every secret the job can read, encoded in base32. GitHub masks secrets in logs, but its documentation says this is not guaranteed once a value has been encoded or otherwise changed. Wiz says the base32 text no longer matches the original secret, so it prints in full.
The workflow sets an empty permissions block. That limits the job's GITHUB_TOKEN, which the attackers do not need, and does not stop the job from reading secrets.
One version of the tool also runs a job for each deployment environment in the repository, so secrets limited to those environments print too. These are often production credentials, according to Wiz.
The tool then downloads the log through GitHub's API and deletes the run seconds later. Because the secrets leave through GitHub itself, there is no attacker server or outbound connection to block.
Since July 28, GitHub has held workflow runs it identifies as potentially malicious until a collaborator with write access approves them. GitHub says the hold "currently applies to public repositories on github.com only" and that GitHub Enterprise Server does not have it at this time.
Every public Gheist run Wiz checked, across all versions of the tool, was still waiting for approval, so its payload never ran.
The hold only catches runs that GitHub flags. A new variant of GhostAction, a separate campaign, ran in public repositories until GitHub began blocking it on October 9, according to research from security company GitGuardian. Wiz says Gheist is distinct from GhostAction, which uses different workflow files.
Around October 19, one version of the tool began pushing a second job meant for self-hosted runners, the machines organizations run themselves to process GitHub Actions jobs. It appears to target only repositories that have such a runner registered.
The job is written to search the runner machine for credentials, including 31 types of tokens: private keys, process environments, AWS instance role credentials, runner credential files, and the Kubernetes service account token. Wiz describes the job as buggy, and its analysis reports no successful run.
The sources Wiz could trace for the stolen tokens include infostealer logs and tokens exposed in earlier supply-chain attacks, such as the March compromise of the Trivy vulnerability scanner.
Other attackers also use the same accounts. On October 6, 391 accounts, many of them also used by Gheist, renamed about 1,461 repositories to appear to be cracked software and spread malware. The renaming wiped 610 of the planted branches.
Some victims also appear to be infected with PolinRider, malware that researchers have linked to North Korea. On October 19 and 20, three of them re-pushed their Gheist commits with a loader added to a vite.config.js file.
Megalodon, a campaign that pushed secret-stealing workflows into thousands of GitHub repositories in May, had also hit 57 of the accounts.
How to Check Your Repositories
Wiz recommends these checks:
- Look for branches named
ci-sync-followed by six characters, where the only change is a new.github/workflows/sync-check.ymlfile with the commit messageci: sync config. - In GitHub audit logs, look for workflow runs on
ci-sync-*branches that were deleted within a minute of finishing, and for any activity from the user agentgheist. - If your workflows sign in to a cloud provider with OIDC, check cloud audit logs for role assumptions or token exchanges whose subject includes a
ci-sync-branch. This works even if you do not collect GitHub logs. - On self-hosted runners, look for the files
.gdmp_pat,.gdmp_patgand.gdmp_sweep, and the stringgdmp-pivotin job logs.
OIDC lets workflows sign in with short-lived tokens instead of stored cloud keys. By default, a token's subject includes the branch name only when the job does not use a deployment environment, according to GitHub's OIDC documentation.
The published indicators are:
- User agent:
gheist - Branch:
^ci-sync-[0-9a-z]{6}$ - Commit message:
ci: sync config, adding only.github/workflows/sync-check.yml - String:
toJSON(secrets) }}' | base32 -w 120 - String:
===== gdmp-pivot: - File:
.gdmp_pat - File:
.gdmp_patg - File:
.gdmp_sweep - Git blob SHA (plain workflow):
f3da2b8b357dcda02fd455d314be2a95007516a6 - Git blob SHA (timeout version):
d09535857a741bbb976bdc084a9a021713133291 - Git blob SHA (separator version):
1dc5af9cce950aad1eb1546ecce8565b117540c4 - Git blob SHA (self-hosted job version):
c665b778b2d822453293003e7ca0bbb2cb08e39d
Versions of the workflow that list a repository's deployment environments vary by repository, so they have no fixed hash.
What to Do If You Find a ci-sync Branch
Wiz advises these steps for an affected repository:
- Rotate every repository, organization, and environment secret the repository could use.
- Revoke the tokens that pushed the commits, and check their owners' devices for infostealers.
- If a ci-sync branch ran on a self-hosted runner, treat the machine and its cloud instance role as compromised.
- Do not approve held sync-check runs, and do not run code from ci-sync branches.
To make a stolen token less useful, Wiz also recommends these steps:
- Require reviewers on environments that hold production secrets.
- Limit OIDC trust policies to protected branches or environments.
- Use GitHub Apps or short-lived fine-grained tokens instead of personal access tokens.
- Run self-hosted runners as short-lived machines without Docker socket access or open access to cloud metadata.
A job cannot read an environment's secrets until a required reviewer approves it, according to GitHub's documentation.
Found this article interesting? Follow us on Google News, Twitter and LinkedIn to read more exclusive content we post.