Hướng dẫn
Phát hiện branch Gheist ci-sync trong repo GitHub
Mục tiêu
Quét mọi repo GitHub mà bạn có quyền truy cập để tìm branch ci-sync-* bị Gheist cài cắm, xác nhận kết quả sạch, và xử lý đúng nếu phát hiện.
Bối cảnh
Wiz Research đã theo dõi Gheist từ 15/09/2026. Một token GitHub bị đánh cắp được dùng để push một branch tên ci-sync- kèm sáu ký tự ngẫu nhiên vào mọi repo mà token đó có quyền. Branch này commit một workflow duy nhất, .github/workflows/sync-check.yml, có nhiệm vụ in secret của repo ra log Actions của chính nó. Log được tải về qua GitHub API rồi run bị xóa chỉ sau vài giây. Wiz đã khôi phục hơn 13.500 branch bị cài cắm từ hơn 850 tài khoản bị xâm phạm, từ dự án cá nhân tới repo private của doanh nghiệp. Tính đến 24/10/2026, chiến dịch vẫn đang tiếp diễn và tiến hóa.
Ba chi tiết khiến đòn tấn công thành công: GitHub chỉ che secret trong log khi nó xuất hiện nguyên văn, nên secret mã hóa base32 in ra đầy đủ; khối permissions: {} trống chỉ giới hạn token GITHUB_TOKEN của chính job, không hạn chế secret mà job được đọc; và nơi repo có deployment environment, một biến thể quét dump qua từng environment, lôi ra cả secret giới hạn theo environment — thường là credential production. Vì secret thoát ra qua chính API của GitHub, không có domain của kẻ tấn công hay kết nối outbound nào để chặn.
Từ 28/07/2026, GitHub giữ các workflow run đáng ngờ trong repo public chờ collaborator duyệt — mọi run Gheist public mà Wiz kiểm tra đều kẹt ở trạng thái action_required, nên các payload đó không bao giờ chạy. Repo private và GitHub Enterprise Server không được bảo vệ. Ở đó, audit log của GitHub cho thấy run trên branch ci-sync-* hoàn tất rồi bị xóa bởi user agent gheist, còn AWS CloudTrail cho thấy chính workflow của tổ chức chạy trên các branch đó và assume AWS role.
Chiến dịch liên tục tiến hóa: ngày 19/10 xuất hiện job thứ hai tên sync-host, nhắm vào repo có self-hosted runner đã đăng ký — nó quét 31 loại token (kể cả key của AI provider, private key, file .env, Terraform state) và thậm chí mount filesystem root của host qua Docker socket. Wiz mô tả job này còn lỗi, chưa thấy run nào thành công, nhưng ý đồ đã rõ. Ngày 18/10, 25 tài khoản Gheist mỗi tài khoản tạo một repo "Windows RDP Runner" trong vòng chín phút, định lạm dụng Actions để đào compute miễn phí.
Dấu hiệu xâm phạm (IOC)
Từ danh sách IOC mà Wiz công bố (25/10/2026), được The Hacker News và CredenShare tóm tắt lại:
- Branch:
ci-sync-kèm sáu ký tự — regex^ci-sync-[0-9a-z]{6}$. Một biến thể dùng hậu tố hệ 16, một biến thể dùng hệ 36. - Commit: message
ci: sync config, chỉ thêm duy nhất file.github/workflows/sync-check.yml. Không ký, đứng tên chủ token. - User agent:
gheisttrong audit log GitHub — tool gửi kèm trong API request. - Chuỗi dấu hiệu:
toJSON(secrets) }}' | base32 -w 120và===== gdmp-pivot:(biến thể self-hosted). - File trên runner:
.gdmp_pat,.gdmp_patg,.gdmp_sweep. - SHA blob của workflow:
f3da2b8b357dcda02fd455d314be2a95007516a6(bản thường),d09535857a741bbb976bdc084a9a021713133291(bản timeout),1dc5af9cce950aad1eb1546ecce8565b117540c4(bản separator),c665b778b2d822453293003e7ca0bbb2cb08e39d(bản self-hosted job). - Vòng đời run: workflow run trên branch
ci-sync-*hoàn tất rồi bị xóa trong khoảng một phút.
Phát hiện
- Fetch và liệt kê branch đáng ngờ trong một repo:
git fetch --all --prune && git branch -a | grep ci-sync-Output mong đợi khi sạch: không có gì. Khi trúng:
remotes/origin/ci-sync-9f2ad1. - Soát commit đơn lẻ của branch đó — chỉ được chạm vào file workflow:
git log --format='%H %an %ae %s' origin/ci-sync-9f2ad1 --not main --max-count=3 git diff --name-only origin/ci-sync-9f2ad1^ origin/ci-sync-9f2ad1Mong đợi với Gheist: một commit duy nhất message
ci: sync config, diff chỉ nêu file.github/workflows/sync-check.yml. So SHA blob của file với danh sách IOC ở trên. - Tìm dấu hiệu dump bên trong workflow bị cài cắm:
git show origin/ci-sync-9f2ad1:.github/workflows/sync-check.yml | grep -E 'base32|toJSON\(secrets\)|gdmp-pivot|sync-host' | head -5Mong đợi với Gheist: các dòng khớp
base32 -w 120và marker dump secret. Đừng dán file này lên dịch vụ paste công cộng — nó nhắc tới tên secret của repo bạn. - Soát audit log GitHub tìm user agent của tool — branch có thể đã bị xóa, nhưng API call vẫn lưu trong log. Dùng giao diện audit-log của org để tìm
gheist, hoặc qua audit-log API:gh api /orgs/ORG/audit-log --paginate -f include='all' -q '.[] | select(.user_agent == "gheist") | [.created_at, .action, .actor, .repo]'Mong đợi khi sạch: không dòng nào. Dòng nào xuất hiện nghĩa là tool đã chạm vào org của bạn qua API.
- Kiểm tra log audit cloud tìm lần assume role từ branch của kẻ tấn công — cách này hiệu quả ngay cả khi bạn không thu thập log GitHub. Trong AWS CloudTrail (hoặc tương đương của provider bạn), tìm event
AssumeRoleWithWebIdentity/ token-exchange mà subject OIDC chứaci-sync-:aws cloudtrail lookup-events --lookup-attributes AttributeKey=EventName,AttributeValue=AssumeRoleWithWebIdentity --max-results 50 --query 'Events[?contains(CloudTrailEvent, `ci-sync-`)]'Mong đợi khi sạch: không event nào. Trúng một event là bằng chứng GitHub Actions đã chạy trên branch của kẻ tấn công.
- Trên mọi self-hosted runner, tìm file phụ trợ và marker của biến thể:
find /home /opt /tmp -maxdepth 4 -name '.gdmp_*' 2>/dev/null; grep -rl 'gdmp-pivot' /var/lib/actions-runner/_diag 2>/dev/null | headMong đợi khi sạch: không output. Có kết quả nghĩa là host runner có thể đã bị quét — coi như đã bị xâm phạm.
Người dùng Wiz Threat Center có thể chạy thêm query Event Explorer từ advisory của Wiz, bao quát commit bị cài cắm, hoạt động Gheist trong audit log GitHub, và các lần assume role cloud từ branch của kẻ tấn công.
Kiểm chứng
Chạy lại bước 1–4 trên mọi repo chung token hoặc chung chủ sở hữu với repo bị ảnh hưởng. Kết quả sạch là: không còn branch ci-sync- nào ở đâu, và không có hit user-agent gheist trong audit log của org trong 90 ngày qua. Lặp lại đợt quét mỗi quý, và ngay sau mọi cảnh báo token bị đánh cắp — log infostealer và các vụ xâm phạm supply-chain trước đó là nguồn token bị đánh cắp mà Wiz truy vết được.
Xử lý
- Xoay (rotate) mọi secret của repo, của org, và của environment mà repo bị ảnh hưởng có thể đọc. Xóa branch hay run không hoàn tác việc lộ secret.
- Thu hồi token đã push các commit đó, và kiểm tra máy của chủ token xem có infostealer không.
- Nếu branch
ci-syncđã chạy trên self-hosted runner, coi host đó và cloud instance role của nó là đã bị xâm phạm. - Không duyệt các run
sync-checkđang bị giữ, và không chạy code từ branchci-sync. - Để lần đánh cắp token sau bớt nguy hiểm: bắt buộc có reviewer trên environment chứa secret production, giới hạn OIDC trust policy chỉ cho branch hoặc environment được bảo vệ, và dùng GitHub App hoặc fine-grained token ngắn hạn thay cho personal access token.
Công cụ của chúng tôi
gheist-guard là CLI local, xác định, chỉ-đọc của chúng tôi để phát hiện đúng mẫu tấn công này: mẫu branch, nhận dạng workflow, nội dung dump, vòng đời run, và user agent gheist — một lệnh, một kết luận cho mỗi repo. Tool không liên kết với Wiz. Những việc nó không làm: không soát audit log cloud của bạn, và không thu hồi token hay xoay secret — đó là bước xử lý của bạn.
Gheist vs GhostAction
Đừng nhầm hai chiến dịch này — chúng khác nhau dù cùng tháng 10/2026. Gheist (Wiz theo dõi) cài sync-check.yml trên branch ci-sync-* và rút secret qua chính API tải log của GitHub — không có máy chủ C2. GhostAction (GitGuardian báo cáo) cài workflow security-audit.yml và rút secret ra máy chủ ngoài (193.32.204[.]199). Theo GitGuardian qua The Hacker News, GhostAction chạm tới 30.000+ repo thuộc 3.000 tổ chức từ 1.900 tài khoản bị xâm phạm. Tên file workflow khác nhau, hành vi mạng khác nhau, nhưng cách chữa giống nhau: xoay secret.
Nguồn
- Wiz Research, "Gheist: Attempted Scaled Abuse of Stolen GitHub Tokens Stumbles" (25/10/2026)
- The Hacker News, "Gheist Uses Stolen GitHub Tokens to Steal Private Repository Secrets via Actions Logs" (tháng 10/2026)
- CredenShare, "Gheist: stolen GitHub tokens used to dump Actions secrets" (27/10/2026)
Cập nhật lần cuối: 2026-10-30. Sửa trên GitHub · Báo lỗi
← Hướng dẫn trước · Hướng dẫn tiếp →
Vẫn kẹt? Nhờ hỗ trợ triển khai →