TECH 으로 돌아가기
TECH HACKER NEWS 9분 읽기 28 READS

탈취된 GitHub 토큰으로 시크릿을 빼내는 'Gheist' 캠페인, GitHub 통제에 발목

탈취된 GitHub 토큰으로 시크릿을 빼내는 'Gheist' 캠페인, GitHub 통제에 발목
SOURCE IMAGE · HACKER NEWS

GitHub 개인용 액세스 토큰(PAT)이 유출되면 해당 토큰이 접근할 수 있는 모든 저장소가 한꺼번에 위험에 빠진다는 사실이 다시 한번 확인됐다. 보안 기업 Wiz의 리서치팀은 2026년 9월 15일부터 'Gheist'라는 이름의 자동화 캠페인을 추적해 왔다. 이 캠페인은 탈취한 토큰으로 접근 가능한 저장소마다 sync-check라는 워크플로를 심어 저장소의 시크릿을 자신의 워크플로 로그에 출력하게 만든 뒤, GitHub API로 그 로그를 내려받고 수초 안에 실행 기록을 삭제한다. API 요청에 실린 사용자 에이전트 문자열 'gheist'가 캠페인 이름의 유래다. Wiz는 지금까지 850개 이상의 계정에서 1만 3,500개가 넘는 심어진 브랜치를 복원했는데, 피해 대상은 개인 토이 프로젝트부터 기업 조직의 비공개 저장소까지 걸쳐 있다.

공격이 작동하는 방식

공격 도구는 각 저장소에 'ci-sync-' 뒤에 임의의 여섯 글자를 붙인 브랜치를 만들고, 'ci: sync config'라는 커밋 메시지로 .github/workflows/sync-check.yml 파일 하나만 추가한다. 커밋은 서명되지 않은 채 토큰 소유자 명의로 올라가며, 이 push 이벤트가 워크플로를 자동 실행시킨다. 핵심 우회 기법은 단순하다. GitHub는 시크릿 값이 로그에 그대로 노출될 때만 마스킹하는데, 공격자는 시크릿을 base32로 인코딩해 출력한다. 인코딩된 값은 원본과 문자열이 일치하지 않으므로 마스킹을 피해 전체가 그대로 찍힌다. 또한 워크플로의 GITHUB_TOKEN 권한을 비워 두더라도(permissions: {}) secrets 컨텍스트 자체는 제한되지 않는다는 점, 배포 환경(deployment environment)이 있으면 이를 잡 매트릭스로 돌려 프로덕션 자격증명 같은 환경 범위 시크릿까지 함께 출력한다는 점이 특히 위험하다. 시크릿이 GitHub 자체 API를 통해 빠져나가기 때문에 차단할 외부 도메인이나 아웃바운드 연결도 존재하지 않는다.

실무자가 주목할 부분은 이 공격이 고정된 결과물이 아니라 활발히 진화하고 있다는 점이다. 브랜치 접미사 형식으로 구분되는 두 변종이 병렬로 관측됐는데, 16진수 접미사를 쓰는 Tool A는 평이한 페이로드를, base36 접미사를 쓰는 Tool B는 저장소별로 페이로드를 바꾸며 timeout-minutes와 환경 매트릭스를 추가했다. 10월 19일 Tool B는 덤프 사이에 구분자(LAFA====)를 넣어 운영자의 로그 파서를 돕는 흔적을 남겼고, 자체 호스팅 러너가 등록된 저장소에는 sync-host라는 두 번째 잡을 추가로 밀어 넣었다. 이 잡은 .gdmp_pat, .gdmp_patg, .gdmp_sweep 세 파일을 만들고 'gdmp-pivot' 헤더 아래 단계별 로그를 남기며, 홈 디렉터리와 시스템 경로에서 Anthropic·Hugging Face·Groq·NVIDIA 등 AI 공급자 키를 포함한 31종 토큰 형식, 개인 키, .env, 테라폼 상태 파일, 셸 기록을 재귀적으로 뒤진다. /proc를 통한 프로세스 환경변수 수집, Docker 소켓을 악용한 호스트 루트 파일시스템 재탐색, 클라우드 인스턴스 자격증명 수집도 시도한다. 다만 이 잡에는 러너 키 파일 경로 오류, 깨진 정규식 등 버그가 있어 GCP·Azure 토큰은 실제로 수집하지 못한다.

GitHub 통제가 공개 저장소를 막았다

이 캠페인에 결정적 제동을 건 것은 GitHub가 2026년 7월 28일부터 적용한 통제다. 공개 저장소에서 악성 가능성이 있는 워크플로 실행은 협업자가 승인하기 전까지 보류된다. Wiz가 확인한 공개 저장소의 Gheist 실행은 자체 호스팅 잡을 포함해 모든 변종에서 전부 action_required 상태에 머물렀고, 악성 페이로드는 끝내 실행되지 않았다. 통제가 의도대로 작동한 것이다. 그러나 이 보류 정책은 비공개 저장소와 GitHub Enterprise Server에는 적용되지 않는다. 실제로 감사 로그에는 ci-sync-* 브랜치에서 실행이 완료된 뒤 gheist 에이전트가 삭제한 기록이, CloudTrail에는 해당 브랜치의 워크플로가 AWS 역할을 떠맡은 기록이 남아 있어 승인 없이 Actions가 실행됐음을 증명한다. 엔터프라이즈 환경에서는 수 분 안에 여러 사용자·자동화 계정 토큰을 돌려 쓰고, 몇 시간 뒤 같은 조직의 클라우드 자격증명으로 AWS Secrets Manager를 열람하는 후속 행위까지 관측됐다.

주목할 또 다른 신호는 탈취된 계정이 여러 위협 행위자 사이를 오간다는 점이다. 유출된 자격증명이 하나의 생태계처럼 공유되면서, Gheist 피해 계정 중 상당수가 크랙 소프트웨어를 위장한 미끼 저장소, GitHub Actions 무료 연산을 노린 크립토마이닝, 빌드 설정 파일에 JavaScript를 숨기는 북한 연계 악성코드 PolinRider, 5월에 활동한 Megalodon 등 다른 캠페인과 겹쳤다. 추적 가능한 자격증명 출처는 인포스틸러 로그와 3월 Trivy 공급망 침해 같은 과거 사고에서 노출된 토큰으로 지목됐다. 참고로 Gheist는 다른 워크플로 파일을 쓰고 특정 외부 IP로 시크릿을 유출하는 GhostAction과는 별개의 캠페인이다.

방어자가 할 일

탐지의 출발점은 ci-sync- 뒤 여섯 글자 패턴(^ci-sync-[0-9a-z]{6}$)의 브랜치, 그리고 .github/workflows/sync-check.yml 하나만 추가하는 'ci: sync config' 커밋이다. GitHub 감사 로그에서는 완료 후 1분 안에 삭제된 ci-sync-* 실행과 gheist 에이전트 활동을 찾아야 한다. 특히 GitHub 로그를 수집하지 않더라도, OIDC로 클라우드에 인증한다면 클라우드 감사 로그에서 주체(subject)에 ci-sync- 브랜치가 포함된 역할 수임·토큰 교환을 확인하는 것만으로 공격자 브랜치에서 Actions가 돌았다는 사실을 잡아낼 수 있다. 자체 호스팅 러너에서는 .gdmp_pat 계열 파일과 로그 속 gdmp-pivot 문자열이 지표가 된다.

대응의 핵심은 실행 기록이나 브랜치를 지운다고 노출이 되돌아가지 않는다는 것이다. 영향받은 저장소가 접근할 수 있는 모든 저장소·조직·환경 시크릿을 교체하고, 커밋을 올린 토큰을 폐기한 뒤 소유자 기기의 인포스틸러 감염 여부를 점검해야 한다. ci-sync 브랜치가 자체 호스팅 러너에서 실행됐다면 해당 호스트와 인스턴스 역할은 침해된 것으로 간주한다. 보류된 sync-check 실행은 승인하지 말고 ci-sync 브랜치 코드는 실행하지 않는 것이 원칙이다. 근본적으로는 프로덕션 시크릿을 쥔 환경에 리뷰어를 요구하고, OIDC 신뢰 정책을 보호 브랜치·환경으로 좁히며, PAT 대신 GitHub App이나 수명이 짧은 세분화 토큰을 쓰고, 자체 호스팅 러너는 Docker 소켓과 메타데이터 접근을 차단한 일회성 호스트로 운영하는 하드닝이 요구된다. Gheist 사례는 결국 공개 저장소를 지켜낸 플랫폼 차원의 통제가 비공개·엔터프라이즈 영역에는 아직 미치지 못한다는 현실을, 그리고 유출된 토큰 하나가 조직 전체 자격증명으로 번지는 경로를 구체적으로 보여준다.

SOURCE · HACKER NEWS
원문 전체 보기 → https://www.wiz.io/blog/gheist-attempted-scaled-abuse-of-sto...
SHARE
NEXT · CHOOSE

변화를 읽었다면,
내가 만들 수익 구조를 고릅니다.

정보를 더 모으는 데서 멈추지 않고, 광고·외주·판매·중개·구독 중 내 상황에 맞는 출발점을 정해보세요.

21가지 수익 구조 살펴보기 →
처리 중...