NPM 웜의 귀환, 더욱 진화된 위협 (TanStack 해킹 사건)

BBetter Stack
컴퓨터/소프트웨어경영/리더십AI/미래기술

Transcript

00:00:00샤이 훌루드가 네 번째 속편으로 돌아왔습니다.
00:00:02이번엔 TanStack 같은 패키지들을 노리고 있죠.
00:00:04제가 Next.js 영상을 올린 지 불과 몇 시간 만에 말이죠,
00:00:07정말 절묘한 타이밍이었습니다.
00:00:08이번 건은 단순한 TanStack을 넘어선
00:00:11대규모 NPM 공급망 공격입니다.
00:00:13UiPath, Mistral 같은 패키지들은 물론,
00:00:15그 외 160개가 넘는 패키지가 포함되었습니다.
00:00:17Guardrails.ai 같은 PyPy 패키지들까지 포함해서요.
00:00:20이번 공격이 더 흥미로운 점은
00:00:22데드맨 스위치가 포함됐다는 겁니다.
00:00:24탈취한 키를 변경했다는 게 감지되면,
00:00:26당신의 PC를 완전히 삭제해 버리죠.
00:00:28게다가 국제 정세 요소까지 반영되어 있습니다.
00:00:30자, 자세히 알아보죠.
00:00:36이번 속편에서 '벌레(The Worm)'의 목표는 동일합니다.
00:00:39개발자 머신과 CI/CD 러너에서 자격 증명을 훔치고,
00:00:42그 자격 증명으로 더 많은 패키지에 접근하는 것이죠.
00:00:44TanStack의 경우, 단 몇 분 만에 42개 패키지에 걸쳐
00:00:4784개의 악성 버전을 배포하는 결과를 낳았습니다.
00:00:51이제 어떻게 TanStack을
00:00:52감염시켰는지 살펴보겠지만,
00:00:54우선 이런 감염된 패키지를 설치하면
00:00:56악성 코드가 어떤 일을 하는지 먼저 보죠.
00:00:58악성 패키지 내부를 보면,
00:00:59routerinit.js라는 새 파일과 함께
00:01:02주입된 옵션 의존성(optional dependency)이 발견됩니다.
00:01:04이 의존성은 겉보기엔
00:01:05합법적인 TanStack 라우터 GitHub 링크처럼 보이지만,
00:01:08사실은 공격자의 포크(fork)에 있는 고립된 커밋입니다.
00:01:10이건 GitHub가 포크 링크를 처리하는 방식일 뿐이라,
00:01:13URL만 봐서는 마치
00:01:14원래 프로젝트의 것인 양 보일 수 있죠.
00:01:16하지만 커밋은 사실 포크에서 온 겁니다.
00:01:18그 포크 안에는 'prepare'라는
00:01:20수명 주기 스크립트가 있어 'bun run task runner JS'를 실행하고,
00:01:22마지막에 exit 1을 포함합니다.
00:01:24이는 페이로드가 실행된 후 옵션 의존성만
00:01:27실패하게 만드는 영리한 방법이죠.
00:01:28그래서 설치는 정상적으로 계속 진행되고,
00:01:30설치 로그에는 흔적을 덜 남기게 됩니다.
00:01:33그리고 제가 아까 언급했던
00:01:35routerinit.js 파일이 실행되지 않는다고 생각할 수도 있겠지만,
00:01:37일단 이 두 파일이
00:01:38이름만 다를 뿐 같은 역할을 한다고 보시면 됩니다.
00:01:40핵심은 설치 시 이 스크립트가 실행된다는 거죠.
00:01:42가장 먼저 하는 일은
00:01:44일반적인 설치 흐름에서 자신을 분리하는 것입니다.
00:01:46그래서 백그라운드에서
00:01:47이미 실행 중인지 확인하고, 아니라면
00:01:50스스로의 분리된 복사본을 생성(fork)한 뒤
00:01:51부모 스크립트를 깔끔하게 종료합니다.
00:01:53이렇게 하면 npm 설치 로그에
00:01:54스크립트의 출력이 전혀 남지 않는데,
00:01:57멀웨어가 이미 프로세스에서
00:01:58분리되어 백그라운드에서 돌고 있기 때문이죠.
00:02:00그 후 아주 영리한 짓을 합니다.
00:02:01자신의 복사본을 당신의 'Clawed Code' 후크 디렉토리에 쓰고,
00:02:04해당 프로젝트에서 Clawed Code를 사용할 때마다
00:02:06이 후크를 실행하도록 설정합니다.
00:02:07이렇게 하면 원래 설치 과정이 끝난 후에도 살아남아
00:02:08프로젝트에서 Clawed Code를
00:02:10열 때마다 계속 재실행됩니다.
00:02:12VS Code의 작업 실행기(task runner)에서도
00:02:13똑같은 짓을 하죠. 그 안에 자신을 복제해서,
00:02:16VS Code의 작업 공간 자동 실행 기능을 쓰면
00:02:17똑같은 문제에 직면하게 됩니다.
00:02:20심지어 'GitHub Token Monitor'라는
00:02:22OS 수준의 서비스까지 설정하는데,
00:02:23그건 나중에 다시 다루죠. 아주 악랄하니까요.
00:02:26아직 구독 안 하신 것도 꽤 악랄하네요.
00:02:28그다음 페이로드가 하는 일은
00:02:29'GitHub Token Monitor'라는 OS 수준의 서비스를 설정하는데,
00:02:31아주 샅샅이 뒤지죠.
00:02:32GitHub Actions에서는 러너 환경 내의
00:02:34자격 증명과 비밀 정보를 찾습니다.
00:02:35더 구체적으로는 마스킹된 비밀 정보를 포함하여
00:02:37GitHub Actions 러너 워커 프로세스 메모리를
00:02:38스크래핑하고,
00:02:40CodeQL처럼 위장한 GitHub 워크플로우를 삽입해
00:02:41저장소 비밀 정보를 직렬화한 뒤 나중에
00:02:43탈취해 갑니다.
00:02:45AWS 비밀 정보도 노리는데,
00:02:47처음에는 환경 변수와 로컬 설정 파일을 노리지만,
00:02:48IMDS v2나 ECS 작업 메타데이터 같은
00:02:50AWS 메타데이터 서비스도 공격합니다.
00:02:52심지어 코드QL처럼 보이는 가짜 GitHub 워크플로우를 삽입해서
00:02:55인증서를 훔쳐 클러스터 내 API 접근 권한을 얻는데,
00:02:57해당 포드의 서비스 계정이 가진 RBAC 권한에 따라,
00:02:58잘못 구성된 클러스터에서는
00:03:00관리자급으로까지 권한이 확장될 수 있습니다.
00:03:02더 나쁜 건 HashiCorp Vault도 노린다는 겁니다.
00:03:03Vault 관련 환경 변수와 토큰을 모조리 수집한 뒤,
00:03:06탈취한 Kubernetes 권한을 이용해
00:03:09Vault로 관리되는 비밀 정보를 모두 가져가죠.
00:03:11이건 단지 CI 배포 환경에 하는 짓일 뿐입니다.
00:03:14워크스테이션에 있다면 SSH 키,
00:03:17NPM 자격 증명, Git 자격 증명,
00:03:19쉘 기록, 클라우드 제공업체 자격 증명,
00:03:21암호화 키, 그리고 시그널, 슬랙,
00:03:22디스코드 파일까지 전부 노립니다.
00:03:24게다가 Clawed Code의
00:03:25HashiCorp Vault까지 노려서,
00:03:27만약 Clawed에 자격 증명을 줬거나,
00:03:29비밀 정보가 포함된 파일을 읽게 했다면,
00:03:30그 정보들도 모두 접근 가능한 겁니다.
00:03:32말씀드렸다시피, 손에 넣을 수 있는
00:03:34모든 것을 노리고 있습니다.
00:03:35그리고 이 데이터는 Session 메신저 네트워크를 통해
00:03:37외부로 유출하죠.
00:03:38백업으로 탈취한 데이터를
00:03:39GitHub 저장소에 올려두기도 합니다.
00:03:41공격 컨셉에 맞춰
00:03:42브랜치 이름도 듄(Dune) 관련 명칭을 쓰죠.
00:03:43자, 자격 증명까지 다 털렸습니다.
00:03:44더 나빠질 게 있을까요?
00:03:45네, 더 있습니다.
00:03:45있고요.
00:03:45아까 머신에 설정된
00:03:46서비스를 기억하시나요?
00:03:47그 서비스는 GitHub 토큰을 계속 모니터링하며
00:03:49재유출 시도를 합니다.
00:03:51매분마다 토큰이 여전히 유효한지 확인하고,
00:03:53만약 유효하지 않다면
00:03:55사용자 디렉토리에 'rm -rf'를 실행해
00:03:56모든 것을 날려버립니다.
00:03:57또한 당신의 자격 증명을 이용해
00:03:58NPM 토큰을 생성하면서,
00:04:00설명란에 이런 문구를 넣습니다.
00:04:02'이 토큰을 취소하면,
00:04:02소유자의 컴퓨터를 삭제하겠다.'
00:04:04GitHub 저장소에 버렸죠.
00:04:05모든 공격의 테마에 맞춰서
00:04:07이 브랜치들은 듄(Dune) 관련 이름으로 명명되었습니다.
00:04:09자, 이제 자격 증명까지 털렸네요.
00:04:11이보다 더 나쁠 순 없겠죠?
00:04:12글쎄요.
00:04:13아니요, 더 나빠질 수 있습니다.
00:04:14그뿐만이 아닙니다.
00:04:15아까 제가 말씀드린
00:04:16여러분의 컴퓨터에 설치된 그 서비스가
00:04:18여러분의 GitHub 토큰을 계속 감시합니다.
00:04:19검사 로직이 포함되어 있습니다.
00:04:21만약 그렇다면
00:04:22그냥 멈춰버리죠.
00:04:24그리고 이스라엘이나 이란의
00:04:25기기로 보이면 1에서 6 사이의
00:04:27무작위 숫자를 생성합니다.
00:04:28그 숫자가 2라면,
00:04:30파괴적인 삭제 명령을 실행하고
00:04:31MP3 파일을
00:04:32최대 볼륨으로 재생합니다.
00:04:33안타깝게도,
00:04:35그 MP3가 무엇인지
00:04:36찾아낼 수는 없었네요.
00:04:38어쨌든,
00:04:39이제 모든 일이 끝났지만,
00:04:40최악의 상황은 아직 오지 않았습니다.
00:04:42이제 겨우 1단계였으니까요.
00:04:442단계는 자기 전파인데,
00:04:46이번 공격에서 가장 위험한 부분입니다.
00:04:47우선,
00:04:48당신의 머신에서 이중 인증(2FA) 없이
00:04:49게시할 수 있는 유효한
00:04:51NPM 토큰을 찾습니다.
00:04:53하나라도 찾으면,
00:04:53해당 계정이 접근할 수 있는 모든 패키지를
00:04:54스캔한 뒤,
00:04:55그 자격 증명을 사용해
00:04:56스스로를 그 패키지들에 추가하고
00:04:58새로운 감염된 버전을 배포합니다.
00:04:59정말 끔찍한 일이지만,
00:05:00애초에 이중 인증을 우회할 수 있는
00:05:01토큰을 방치해 두는 건
00:05:03좋지 않은 일입니다.
00:05:04가장 무서운 부분은,
00:05:05이 공격이 CI/CD 내에서
00:05:05실행될 때 발생하는 일입니다.
00:05:07CI 환경에서는,
00:05:07공격자가 수명이 긴
00:05:08NPM 토큰이 필요하지 않은데,
00:05:09제대로 구축된 환경이라면
00:05:11OIDC를 사용하기 때문이죠.
00:05:13이 부분은 나중에 더 자세히 다루겠습니다.
00:05:15그럼 이제,
00:05:16무엇이 문제인지
00:05:16다시 한번 짚어보죠.
00:05:17사실 많은 개발자가
00:05:19자신의 자격 증명을
00:05:19너무 쉽게 다루고 있습니다.
00:05:21이제 어떻게 이런 공격을
00:05:22방지할 수 있을지
00:05:24살펴볼 시간입니다.
00:05:26가장 먼저 해야 할 일은
00:05:26의존성 검사를 강화하는 것인데,
00:05:28이는 매우 기초적인 단계입니다.
00:05:30하지만 그것만으로는 충분하지 않습니다.
00:05:32더 나아가, 개발 환경에서
00:05:33어떤 스크립트가
00:05:33실행되는지 모니터링해야 합니다.
00:05:34우회할 수 있는
00:05:352단계 인증을
00:05:36더 무서운 버전의 이 공격은
00:05:38어떤 일이 벌어질지
00:05:39CI/CD 내부에서 실행될 때입니다.
00:05:41왜냐하면 CI에서는
00:05:42공격자가 굳이
00:05:43장기 NPM 토큰이
00:05:44필요 없기 때문이죠.
00:05:45좋은 설정들은 종종 OIDC를 사용하는데,
00:05:47이게 더 안전하다고 여겨집니다.
00:05:48본질적으로,
00:05:49NPM 토큰을
00:05:50비밀값으로 저장하는 대신,
00:05:51GitHub Actions가 NPM에 증명합니다.
00:05:53“저기,
00:05:53내가 이 저장소이고
00:05:54이 워크플로우를 실행 중이며
00:05:55이 브랜치에서 실행 중이야.”
00:05:56그러면 NPM은
00:05:57단기 게시용 토큰을 줍니다.
00:05:59하지만 여기서 문제는
00:06:00스크립트가 권한을 얻으면
00:06:01신뢰받는 GitHub Actions 환경에 접근하여
00:06:03합법적인 게시자와 동일한 위치에
00:06:04설 수 있다는 점입니다.
00:06:06그래서 멀웨어는
00:06:07GitHub이 작업에 노출하는
00:06:08OIDC 관련 환경을 사용하여
00:06:10GitHub 토큰 엔드포인트에서
00:06:12OIDC JWT 토큰을 요청합니다.
00:06:14그 다음 그 JWT 토큰을
00:06:16NPM과 교환하여
00:06:17단기 게시용 토큰을 받습니다.
00:06:18NPM 신뢰 게시 시스템을
00:06:19통해서 말이죠.
00:06:20이제 공격자는
00:06:22영구적인 NPM 토큰을
00:06:22훔칠 필요 없이
00:06:24완전히 합법적으로 보이며 게시할 수 있습니다.
00:06:26이 경우,
00:06:26멀웨어는 그 router init.js 파일
00:06:27복사본을 패키지 테이블에
00:06:29함께 묶어두고,
00:06:30악성 선택적 의존성을
00:06:31추가한 뒤,
00:06:32전부 최신 태그로
00:06:33그 패키지를
00:06:34게시합니다.
00:06:35그래서 누군가
00:06:35또는 CI/CD 파이프라인이
00:06:37이 패키지들을 설치하면
00:06:38루프가 다시 시작되어
00:06:40가능한 한 멀리
00:06:40퍼져나가게 됩니다.
00:06:42정말
00:06:42미친 소리 같죠?
00:06:43하지만 이제
00:06:44환자 제로인,
00:06:46TanStack에 집중해 봅시다.
00:06:46어떻게 처음부터
00:06:47감염된 걸까요?
00:06:48글쎄요,
00:06:49그들의 사후 분석에 따르면
00:06:50공격자가 그
00:06:51GitHub Actions 파이프라인을 악용했습니다.
00:06:53그들은 악성 패키지가
00:06:53실제로 게시되기 전날부터
00:06:54움직였습니다.
00:06:56TanStack router의 포크를 만들었는데
00:06:57이름을
00:06:58configuration으로 바꿔서
00:06:59찾기 어렵게
00:06:59만들려고 했죠.
00:07:01뻔한 포크 이름들을
00:07:02검색해서 찾기 힘들게요.
00:07:04그러고 나서 그들은
00:07:04이 포크에 악성 커밋을
00:07:05추가했는데,
00:07:06Claude가 작성한 것처럼 조작했고
00:07:07커밋 메시지에는
00:07:07skip CI가
00:07:08접두어로 붙어서
00:07:09푸시 이벤트 시 바로
00:07:10CI가 실행되지 않게 했습니다.
00:07:11다음 날,
00:07:13그들은 TanStack router에
00:07:13PR을 열었는데
00:07:14이름은 '진행 중인 작업(WIP):
00:07:15기록 빌드 단순화'였습니다.
00:07:16여기서 실제 공격이 발생하죠.
00:07:18요약하자면
00:07:18TanStack은 bundle-sized GitHub Actions 워크플로우를
00:07:20사용했는데 그게
00:07:21pull request target을
00:07:22사용했다는 점이 주목할 만합니다.
00:07:23왜냐하면 pull request target은
00:07:25포크가 아니라
00:07:26베이스 저장소 보안 컨텍스트에서
00:07:27실행되기 때문이죠.
00:07:28즉, 베이스 저장소의
00:07:29캐시 범위와
00:07:30GitHub 토큰에
00:07:31접근할 수 있다는 뜻입니다.
00:07:32그래서 이 워크플로우는 PR을 체크아웃하고,
00:07:33의존성을 설치한 뒤,
00:07:35벤치마크 빌드를 실행했습니다.
00:07:35하지만 문제는 그 포크에
00:07:36악성 코드가 포함되어 있었다는 점입니다.
00:07:38이 경우,
00:07:39PNPM 패키지 저장소를
00:07:40오염시키는
00:07:40셋업 스크립트였는데,
00:07:41릴리스 액션이
00:07:42나중에 사용할
00:07:43바로 그 캐시 키 아래에서
00:07:44말이죠.
00:07:45그들은 워크플로우가 사용하는
00:07:47정확한 수식을 사용하여
00:07:48공용 PNPM 락 파일을 통해
00:07:49이를 미리 계산했습니다.
00:07:50오염된 캐시가 저장되자,
00:07:51그들은 그 브랜치를
00:07:52현재 메인 브랜치와 일치하도록
00:07:54재설정했습니다.
00:07:56그래서 보이는 PR은
00:07:57파일 변경이 없는
00:07:57노옵(no-op)처럼 보였고,
00:07:58그 뒤 그들은
00:07:59해당 PR을 닫고
00:07:59악성 브랜치를 삭제했습니다.
00:08:00외부에서 보면
00:08:01아무 일도 일어나지 않은 것처럼
00:08:02보이지만,
00:08:03그들은 GitHub Action 캐시를
00:08:04오염시킨 겁니다.
00:08:05즉, 8시간 후,
00:08:06평범한 관리자가
00:08:07관련 없는 PR을
00:08:07메인에 병합했을 때,
00:08:08TanStack의
00:08:09릴리스 워크플로우가 트리거되어
00:08:10그 GitHub 액션 캐시를 오염시킨 거죠.
00:08:11이제 공격자가 제어하는 코드가
00:08:12그 릴리스 액션 내부에서
00:08:13실행되게 된 겁니다.
00:08:14그 후 OIDC와 동일한 로직을 사용하여
00:08:15NPM 게시 토큰을 얻었고,
00:08:1642개의 TanStack 패키지에 걸쳐
00:08:17자기 자신의
00:08:1884개 버전을 게시했습니다.
00:08:19심지어 액션의
00:08:20패키지 게시 단계까지
00:08:22갈 필요조차 없었습니다.
00:08:23우스운 점은,
00:08:24일부 테스트가 실패해서
00:08:25액션이 실제로 실패했는데,
00:08:26그 단계까지 도달하지 못했음에도
00:08:28악성 코드가 실행되어
00:08:29그 모든 것을
00:08:30어쨌든 게시해 버렸다는 거죠.
00:08:32공격자는 이렇게
00:08:33세 개의 신뢰 경계를
00:08:34연쇄적으로 통과했습니다.
00:08:35첫째,
00:08:36포크 PR 코드가
00:08:36베이스 저장소의 캐시를 오염시켰고,
00:08:37둘째,
00:08:39베이스 저장소의 캐시가
00:08:40실제 릴리스 워크플로우 안에서 복원되었으며,
00:08:41셋째,
00:08:43실제 릴리스 워크플로우가
00:08:43OIDC 권한을 가지고 있어서
00:08:44NPM 게시 권한으로 변환되었기에
00:08:46완전히
00:08:47합법적으로 보이는 패키지를
00:08:47게시할 수 있었던 겁니다.
00:08:48이게 바로 제가 생각하는
00:08:49공급망 공격의
00:08:51정말 무서운 점입니다.
00:08:52그들은 이제 한 관리자의 토큰을
00:08:53훔치는 것에서 벗어나
00:08:54CI/CD 시스템 자체를
00:08:56악용하는 쪽으로 가고 있습니다.
00:08:57즉, 우리의 모든 신뢰 신호가
00:08:58오히려 공격자를 위해
00:08:59작동하기 시작했다는 겁니다.
00:08:59이건 실제 워크플로우에 의해 게시된
00:09:01유효한 증명을 가진
00:09:02서명된 패키지였습니다.
00:09:03자, 여기까지가 ShaiHalud4입니다.
00:09:05혹시라도 이 패키지 중 하나로
00:09:05공격받았는지
00:09:06확인하고 싶으시다면,
00:09:07제가 아래에
00:09:08블로그 포스트 링크를 남겨둘게요.
00:09:10어떻게 알 수 있는지,
00:09:11만약 설치했다면
00:09:12무엇을 해야 하는지가
00:09:13담겨 있습니다.
00:09:14이 모든 상황과
00:09:15NPM 생태계에 대해
00:09:16어떻게 생각하는지 댓글로 알려주세요.
00:09:18댓글 남기는 김에
00:09:19바로 ShaiHalud4입니다.
00:09:20그럼 늘 그렇듯,
00:09:21다음 영상에서 뵐게요.
00:09:21이런 패키지들에 의해
00:09:23제가 링크를
00:09:23아래 블로그 포스트에 남겨둘게요.
00:09:25그 포스트에서
00:09:25어떻게 확인할 수 있는지,
00:09:26그리고 어떻게 대처해야 하는지
00:09:27이 패키지들 중 하나라도
00:09:28설치했다면 알 수 있을 겁니다.
00:09:29이 모든 것에 대해
00:09:30여러분의 생각이 어떤지
00:09:30댓글로 알려주시고,
00:09:31NPM 생태계에 대해서도요.
00:09:33댓글 남기는 김에,
00:09:33구독도 부탁드려요.
00:09:34언제나 그렇듯,
00:09:34다음 영상에서 뵐게요.

Key Takeaway

공격자는 GitHub Actions의 캐시와 OIDC 권한을 악용하여 단기 게시 토큰을 탈취함으로써 160개가 넘는 패키지를 합법적인 개발 환경에서 감염시켰습니다.

Highlights

  • ShaiHulud4 NPM 공급망 공격으로 TanStack을 포함한 160개 이상의 패키지가 감염되어 42개 패키지에서 84개의 악성 버전이 배포됨.

  • 악성 패키지는 GitHub 포크의 고립된 커밋을 활용해 합법적인 프로젝트인 것처럼 가장하며 설치 로그에 흔적을 최소화함.

  • 설치된 멀웨어는 'GitHub Token Monitor' OS 서비스를 설정하여 환경 변수, SSH 키, 슬랙 및 디스코드 데이터 등 모든 정보를 탈취함.

  • 공격자는 GitHub Actions의 캐시 오염을 통해 릴리스 워크플로우를 가로채고 OIDC 토큰으로 NPM 게시 권한을 획득함.

  • 데이터 유출 실패 시 데드맨 스위치가 작동하여 사용자 디렉토리를 'rm -rf' 명령으로 삭제하고 최대 볼륨으로 MP3를 재생함.

Timeline

ShaiHulud4 공격의 범위와 목적

  • 이번 공격은 TanStack을 포함해 160개 이상의 NPM 및 PyPy 패키지를 대상으로 함.
  • 개발자 머신과 CI/CD 환경에서 자격 증명을 탈취하는 것이 핵심 목표임.
  • 감염된 패키지는 불과 몇 분 만에 84개의 악성 버전을 배포함.

ShaiHulud4라는 이름의 이번 공급망 공격은 대규모로 진행되었습니다. UiPath, Mistral, Guardrails.ai 등 다수의 유명 패키지가 포함되었으며, 단순히 키를 탈취하는 것을 넘어 탐지 시 PC를 삭제하는 데드맨 스위치 메커니즘을 갖추고 있습니다.

악성코드의 잠복과 설치 전략

  • 옵션 의존성을 위장한 GitHub 포크의 고립된 커밋을 통해 악성 스크립트를 실행함.
  • 설치 스크립트는 자체 분리되어 백그라운드에서 실행되므로 npm 로그에 기록되지 않음.
  • VS Code 작업 실행기 및 Clawed Code 후크에 자신을 복제하여 지속성을 확보함.

멀웨어는 설치 과정에서 영리하게 자신을 부모 프로세스로부터 분리합니다. 이후 VS Code나 Clawed Code 환경에 자신을 심어, 원래 설치가 끝난 뒤에도 사용자가 관련 도구를 실행할 때마다 재감염되도록 설계되었습니다.

CI/CD 환경 및 자격 증명 탈취

  • GitHub Actions 러너의 메모리를 스크래핑하여 마스킹된 비밀 정보를 탈취함.
  • AWS 메타데이터 서비스 및 HashiCorp Vault 환경 변수와 토큰을 수집함.
  • 모든 탈취 데이터는 Session 메신저 네트워크를 통해 외부로 유출됨.

공격은 워크스테이션을 넘어 CI/CD 배포 환경 전반을 타격합니다. 특히 가짜 GitHub 워크플로우를 삽입해 RBAC 권한을 확장하고, 클러스터 내부의 중요한 비밀 정보를 모두 가로채는 치밀함을 보입니다.

공급망 오염의 핵심: 릴리스 워크플로우 가로채기

  • 공격자는 PR 단계에서 GitHub Actions의 캐시를 오염시켜 릴리스 워크플로우를 장악함.
  • OIDC JWT 토큰을 NPM 게시용 단기 토큰으로 교환하여 정식 배포자인 것처럼 행동함.
  • 테스트가 실패한 상황에서도 악성코드가 실행되어 감염된 버전이 게시됨.

가장 심각한 단계는 신뢰 신호를 악용하는 방식입니다. 공격자는 포크된 PR에서 캐시를 미리 오염시킨 뒤, 이후 실제 릴리스 시점에 그 캐시가 복원되면서 합법적인 OIDC 권한을 가진 워크플로우가 악성 코드를 게시하도록 만들었습니다.

Community Posts

No posts yet. Be the first to write about this video!

Write about this video