Mika Ayenson, PhD

CI/CD 파이프라인 남용: 아무도 보고 있지 않은 문제

신호 추출 및 LLM 추론을 사용하여 GitHub Actions, GitLab CI 및 Azure DevOps 파이프라인에서 CI/CD 남용을 포착하는 오픈 소스 드롭인 CI 템플릿을 구축한 방법을 알아보세요.

서문

2025 와 2026 년에는 업계 전반에 걸쳐 패턴이 나타나는 것을 목격했습니다. 공격자들은 프로덕션 서버를 직접 공격하는 것을 멈추고 서버에 배포되는 자동화를 표적으로 삼기 시작했습니다. 손상된 개발자 자격 증명, 수정된 워크플로 파일, 그리고 갑자기 CI/CD 환경의 모든 비밀이 공격자가 제어하는 엔드포인트로 스트리밍되고 있습니다. 주요 오픈소스 프로젝트, Fortune( 500 ) 기업, 중요 인프라 도구와 관련된 사고에서 이러한 현상이 발생하는 것을 확인했습니다.

공격 사슬은 놀라울 정도로 간단합니다:

개발자 자격 증명 도용 → 수정된 워크플로 파일 → 수집된 CI 비밀 → 클라우드 및 프로덕션으로의 측면 이동

현재 저희는 정규식 기반 신호 추출과 LLM 분석을 사용하여 CI/CD 파이프라인의 의심스러운 변경 사항을 탐지하는 드롭인 CI 템플릿인 ccd-abuse-detector를 오픈 소스화했습니다. 이 기능은 GitHub Actions, GitLab CI 및 Azure DevOps에서 작동하며 공공 보안 연구에 문서화된 실제 공격 기법을 중심으로 설계되었습니다.

핵심 사항

  • CI/CD 환경은 손상된 단일 워크플로우가 클라우드 자격 증명, 패키지 레지스트리 토큰, 코드 서명 키, 배포 키, OIDC 토큰을 동시에 유출할 수 있기 때문에 가치가 높은 공격 대상입니다.
  • 이 도구는 50개 이상의 정규식 및 메타데이터 신호를 Diff에서 추출한 다음, 구조화된 위협 분석을 위해 전체 Diff와 함께 Claude에 전달합니다. Python, bash 및 Claude Code CLI 이외의 종속성 없음
  • 탐지 패턴은 Nord StreamGato-X와 같은 공격 툴킷과 ArtiPACKEDHackerBot-Claw를포함한 실제 사고에 대해 테스트되었습니다.
  • 이 프로젝트는 특정 인시던트를 모델로 한 19 악성 및 4개의 양성 예제 디프와 모든 신호를 검증하는 자동화된 테스트 스위트를 함께 제공합니다.

CI/CD 파이프라인이 최우선 목표인 이유

GitHub Actions 또는 GitLab CI 구성을 검토하는 데 시간을 할애하면 이러한 파일에 얼마나 많은 신뢰가 집중되어 있는지 알 수 있습니다. 일반적인 배포 워크플로에서는 AWS 자격 증명, npm 게시 토큰, Docker Hub 비밀번호, 쓰기 권한이 있는 GitHub 토큰에 동시에 액세스할 수 있습니다. 공격 표면은 CVE가 있는 서버가 아니라 YAML 파일입니다.

대규모 자격증명 수집

개발자 자격 증명을 탈취한 공격자는 CI 환경에서 사용 가능한 비밀을 유출하기 위해 워크플로우를 수정합니다. 9월에 있었던 고스트액션() 캠페인은 리포지토리에서 2025 327 GitHub 사용자를 감염시켜 이를 대규모로 817 입증했습니다. 3,325개의 비밀이 공격자 엔드포인트에 자격 증명을 게시하는 삽입된 워크플로 파일을 통해 도난당했습니다.

Shai-Hulud npm 웜은 더 나아갔습니다. 이 자가 전파 공격은 gh 인증 토큰을 통해 GitHub 개인 액세스 토큰을 수집하고, 비밀 정찰을 위해 트러플호그를 실행하고, 손상된 토큰을 사용하여 동일한 개발자가 소유한 다른 패키지에 악성 코드를 조용히 주입했습니다. 첫 번째 공격에서만 46,000개 이상의 악성 패키지가 게시되었습니다.

권한 트리거 익스플로잇

pull_request_target 트리거는 GitHub 액션에서 가장 위험한 기능 중 하나입니다. 일반 pull_request 트리거와 달리, 시크릿에 액세스할 수 있는 기본 리포지토리의 컨텍스트에서 워크플로를 실행하지만 신뢰할 수 없는 포크에서 코드를 실행할 수 있습니다. Orca "풀 리퀘스트 악몽" 연구는 Google, Microsoft, NVIDIA에서 관리하는 리포지토리를 대상으로 이를 입증했습니다.

2026년 2월, HackerBot-Claw라는 자동화된 캠페인이 공개 리포지토리를 체계적으로 스캔하여 이러한 잘못된 구성이 있는지 확인했습니다. 포이즌된 Go init() 함수, 분기 이름 명령 주입, 파일 이름 기반 주입, 직접 스크립트 주입, Claude 기반 코드 리뷰어에 대한 AI 프롬프트 주입 등 5가지 익스플로잇 기법을 사용했습니다. 가장 심각한 사례로 아쿠아 시큐리티의 트리비 리포지토리가 완전히 손상되어 다운스트림 공급망 공격으로 이어져 약 7,000대의 컴퓨터에서 33,000개의 기밀이 노출된 사건이 발생했습니다. 문서화된 바와 같이, 이 공급망 공격은 최초 도난 후 몇 주 동안 유효했던 손상된 토큰을 통해 이루어졌습니다.

나머지 분류 체계

이 위협 모델은 인증정보 수집과 트리거 익스플로잇 외에도 공개 연구에서 일관되게 나타나는 네 가지 범주를 추가로 다룹니다:

  • 권한 에스컬레이션: 쓰기-모두 또는 아이디 토큰: 쓰기 권한을 추가하면 모든 침해의 폭발 반경이 넓어집니다.
  • 러너 타겟팅, 내부 인프라에 대한 네트워크 액세스 권한이 있는 자체 호스팅 러너로 작업을 리디렉션하거나 공격자가 제어하는 컨테이너 이미지를 지정합니다.
  • 변경 가능한 액션 참조를 통한 공급망 조작(SHA 고정 버전 대신 @main 사용), 원격 스크립트 실행(curl | bash), 잠금 파일 레지스트리 스왑, 종속성 중독.
  • 커밋 타임스탬프 조작을 통한 방어 회피로 악성 파일을 오래되고 신뢰할 수 있는 파일로 보이게 합니다. KL4R10N은 북한과 연계된 캠페인에서 이 기법을 문서화했는데, 백데이트된 커밋은 주장한 날짜에 존재하지 않았던 인프라를 참조했습니다.

이들 각각은 특정 MITRE ATT& CK 기법에 매핑됩니다: T1552 (보안되지 않은 자격 증명), T1195 (공급망 손상), T1070.006 (타임스탬프) 및 T1059 (명령 및 스크립팅 인터프리터).

감지기의 작동 방식

Python, 사용자 지정 런타임 또는 복잡한 종속성 없이도 템플릿이 작동하기를 원했습니다. 모든 것이 기본 우분투 최신 런처의 표준 셸 유틸리티에서 실행되며, 유일하게 설치된 도구는 인증, 재시도 및 모델 라우팅을 처리하는 npm을 통한 클로드 코드 CLI뿐입니다.

1단계: 필터 및 차이점

풀 리퀘스트가 열리거나 푸시가 보호된 브랜치에 도착하면 워크플로에서 CI/CD 관련 경로의 세 가지 계층에서 변경된 파일을 식별합니다. 첫 번째 계층은 워크플로 정의, 파이프라인 구성 및 메이크파일과 같은 핵심 CI 파일을 다룹니다. 두 번째는 도커파일, 패키지 매니페스트, 잠금 파일, 서명 또는 배포 스크립트와 같은 빌드 및 릴리스 아티팩트를 다룹니다. 세 번째 계층은 .vscode/tasks.json 및 .devcontainer와 같은 개발자 환경 구성을 선택합니다. 파일.

각 파일은 개별적으로 다르며 10,000자로 제한됩니다. 결합된 차이의 단일 캡은 바이패스 벡터이기 때문에 전역이 아닌 파일별로 이 작업을 수행합니다. 공격자는 악의적인 워크플로 변경에 양성 도커파일 편집을 크게 추가하여 익스플로잇을 글자 수 제한 이상으로 밀어붙일 수 있습니다.

2단계: 신호 추출

LLM이 어떤 것을 보기 전에 50개 이상의 정규식 패턴이 각각의 차이를 검사하여 알려진 위험 패턴을 찾습니다. 이러한 신호는 권고 사항입니다. 분석에 대한 게이트는 없지만 미리 선별된 위협 요약을 LLM에 제공합니다. 몇 가지 예를 들어보겠습니다:

신호패턴잡는 대상
secrets_context${{.*secrets.워크플로우에서 직접 비밀 보간하기
pull_request_targetpull_request_targetPR 코드에 비밀을 부여하는 위험한 트리거
checkout_refref:.*github.event.pull_request.head.(sha|ref)권한 있는 컨텍스트에서 체크 아웃된 신뢰할 수 없는 PR 코드
double_base64base64.*|.*base64로그 마스킹을 회피하기 위한 이중 인코딩(Nord Stream 기술)
ld_preloadLD_PRELOAD환경 변수 주입을 통한 임의 코드 실행
vscode_auto_taskrunOn.*folderOpen폴더가 열리면 실행되는 VS 코드 작업(전염성 인터뷰)

이 신호 목록은 Nord StreamGato-X를 비롯한 실제 공격 툴을 기반으로 하며, 특정 인시던트를 모델로 한 19 악성 예제 디프에 대해 테스트했습니다.

이 탐지기는 GitHub Actions, GitLab CI 및 Azure DevOps에서 동일하게 실행됩니다. 각 플랫폼에서 실행되는 탐지 기능은 다음과 같습니다:

3단계: LLM 분석

신호 요약, 전체 차이점, 작성자 프로필, 커밋 메타데이터는 번들로 제공되며 Claude Code CLI를 통해 Claude로 전송됩니다. 분석 프롬프트는 여러 영역을 통해 모델을 안내합니다:

  1. 차이 이해도 및 파일별 위험 평가
  2. 컨텍스트를 통한 신호 해석(신호만으로는 판결이 아님)
  3. 백데이트된 커밋에 대한 시간적 분석
  4. 계정 나이, 기여 내역 및 조직 멤버십을 사용한 작성자 신뢰도 평가
  5. 60개 이상의 항목이 있는 신호 조합 테이블에 대한 심각도 보정
  6. 오탐 인식(예: 알려진 도구를 다운로드하기 위한 cURL은 유출이 아님)
  7. 구체적이고 실행 가능한 권장 사항 ("actions/setup-node@main을 특정 SHA에 고정" 대신 "주의 깊게 검토")

출력은 심각도, 신뢰도, 추론, 증거 및 권장 사항을 포함하는 구조화된 JSON 평결이며, 모두 JSON 스키마에 대해 유효성이 검사됩니다.

4단계: 경고 및 게이트

평결 심각도에 따라 워크플로에서는 단계 요약을 게시하고, 이슈를 만들고, Slack 알림을 보내고, 심각도가 구성된 임계값을 충족하는 경우 선택적으로 PR 확인에 실패합니다.

Slack 및 GitHub 이슈의 알림은 즉각적인 알림 문제를 해결하지만 쿼리 가능한 기록은 제공하지 않습니다. 탐지기가 생성하는 모든 판정(예 양성, 의심스러운 또는 악의적인), 선택적으로 logs-cicd.abuse-default의 구조화된 문서로 Elasticsearch에 전송할 수 있습니다. 데이터 스트림. 워크플로는 지원되는 세 가지 플랫폼에 모두 적용되는 단일 인덱스에 CI/CD 메타데이터(플랫폼, 리포지토리, 액터, 이벤트 유형, 실행 URL)와 함께 판결을 제공합니다.

바로 이 지점에서 크로스 플랫폼 상관관계가 실용화됩니다. 동일한 액터에서 발생한 GitHub Actions 알림과 GitLab CI 알림은 동일한 데이터 스트림에 도착하며, 단일 ES|QL 문으로 쿼리할 수 있습니다:

FROM logs-cicd.abuse-* 
WHERE verdict.verdict IN ("malicious", "suspicious") AND @timestamp > NOW() - 7 days 
EVAL platform = cicd.platform, repo = cicd.repository, actor = cicd.actor, severity = verdict.severity
KEEP @timestamp, platform, repo, actor, severity
SORT @timestamp DESC

스키마에는 cicd.platform이 포함됩니다, cicd.repository, 및 전체 평결 객체(평결, 심각도, 신뢰도, 요약, 이유, 증거)를 사용하여 탐지 규칙을 간단하게 구축할 수 있습니다. 1시간 이내에 여러 리포지토리를 공격하는 조직적인 캠페인, 여러 플랫폼에서 반복적으로 신고된 위반자, 인시던트 대응 페이지가 필요한 중요한 발견 사항의 급증 등은 서로 연관되어 있을 수 있습니다.

실제 공격에 대한 검증

커버리지를 검증하기 위해 공격 도구의 실제 소스코드, 발표된 연구 및 공개 사후 분석과 당사의 탐지 패턴을 비교했습니다.

Nord Stream: 문자 그대로의 페이로드 매칭

Nord Stream은 Synacktiv의 오픈 소스 CI/CD 비밀 추출 도구로 GitHub, GitLab 및 Azure DevOps를 지원합니다. YAML 생성기 소스(nordstream/yaml/github.py)를 가져와서 출력 템플릿을 예제 차이점과 비교했습니다.

  • GitHub 페이로드 템플릿은 env -0 | awk -v RS='0' '/^secret_/ {print $0}' | base64 -w0 | base64 -w0 을 사용합니다. nord-stream-pipeline-exfil.diff 에는 이 줄이 그대로 포함되어 있으며 double_base64, env_null_dump, env_secret_grep 에는 모두 화재 신호가 표시됩니다.
  • OIDC Azure 템플릿은 id-token: write 권한과 az 계정 get-access-token | base64 -w0 | base64 -w0 뒤에 azure/login@v1 을 사용합니다. 이 정확한 흐름을 포착하여 cloud_auth_actionid_token_write 을 트리거합니다.
  • Azure DevOps 파이프라인 기술(addSpnToEnvironment SPN 자격 증명 노출, DownloadSecureFile 보안 파일 도용, ssh.js 수정을 통한 SSH 작업 소스 패치)은 모두 nord-stream-azure-devops.diff 에 있으며 플랫폼별 신호로 감지됩니다.

ArtiPACKED: 아티팩트 경쟁 조건

팔로알토 유닛( 42 )의 ArtiPACKED 연구에 따르면 전체 체크아웃 디렉터리를 아티팩트로 업로드하면 GITHUB_TOKEN 파일이 포함된 .git/config 파일이 유출되는 것으로 나타났습니다. v4 아티팩트 API는 실행 중 다운로드를 허용하기 때문에 공격자는 작업이 완료되기 전에 토큰을 추출하여 사용할 수 있습니다.

저희 artifact-token-leak.diff 에서는 upload-artifactpath: . (전체 작업 영역)을 사용하여 이 패턴을 정확하게 모델링합니다. upload_artifact 신호가 이를 포착하면 LLM은 업로드 범위에 .git 디렉터리가 포함되어 있는지 여부를 평가합니다.

GITHUB_ENV 주입: LD_PRELOAD를 RCE로

구글 파이어베이스와 아파치에 대한 레짓시큐리티의 연구 결과, 공격자가 $GITHUB_ENV 에 신뢰할 수 없는 입력을 작성하면 LD_PRELOAD, NODE_OPTIONS 와 같은 임의의 환경 변수를 설정하여 권한이 있는 워크플로에서 코드를 실행할 수 있는 것으로 나타났습니다.

github-env-injection.diff 는 악성 공유 개체를 가리키는 LD_PRELOAD, 필수 인젝션이 포함된 NODE_OPTIONS, $GITHUB_PATH 조작 등 세 가지 페이로드를 사용하여 이 기법을 재현합니다. github_env_write, ld_preload, github_path_write 신호는 모두 예상대로 트리거됩니다.

전염성 인터뷰: 초기 액세스로 IDE 구성

북한 소행으로 추정되는 전염성 인터뷰 캠페인은 가짜 면접을 통해 개발자를 표적으로 삼고, 폴더를 열면 자동으로 실행되는 .vscode/tasks.json 파일이 포함된 리포지토리를 배포합니다. 프레젠테이션은 숨겨져 있으며(reveal: never, echo: false), 페이로드는 자동 실행을 위해 curl | node 을 사용합니다.

저희의 ide-config-poisoning.diff 는 자동 실행 트리거(runOn: folderOpen), 숨겨진 프레젠테이션, curl | node 페이로드, .vscode 디렉터리를 숨기는 files.exclude 항목, 코드 실행을 위해 base64로 인코딩된 URL과 eval() 를 포함하는 트로이 목마화된 포스트 인스톨 후크를 포함한 전체 공격 체인을 캡처합니다. 6개의 신호가 한 번에 이를 포착합니다.

방어 권장 사항

탐지기를 배포하는 것 외에도 저희가 연구한 공격 패턴에서 직접 도출한 몇 가지 강화 조치는 다음과 같습니다:

  • 모든 작업을 브랜치가 아닌 태그가 아닌 SHA에 고정합니다. SHA로 고정된 참조는 tj-actions (CVE-2025-30066)와 같은 소급 태그 수정 공격을 방지합니다.
  • 작업 수준 환경 변수를 사용하지 않고 개별 단계로 비밀 범위를 지정합니다. 각 단계는 실제로 필요한 비밀에만 액세스할 수 있어야 합니다.
  • 가능하면 수명이 짧은 임시 토큰을 사용하여 공격 표면을 줄이세요.
  • 꼭 필요한 경우가 아니면 pull_request_target 을 사용하지 마세요. 반드시 사용해야 하는 경우 동일한 워크플로에서 PR 헤드 코드를 체크 아웃하지 마세요. 비밀과 PR 컨텍스트가 모두 필요한 작업에는 별도의 workflow_run-triggered workflow 을 사용하세요.
  • 기본 토큰 권한이 너무 광범위하므로 모든 워크플로에 명시적인 권한을 설정하세요. 워크플로 수준에서 permissions: {} 을 설정하고 작업별 특정 권한을 추가합니다.
  • 액션/체크아웃의 기본 동작은 .git 디렉터리의 GITHUB_TOKEN 을 유지하므로 결제 시 persist-credentials: false 을 활성화합니다. 아티팩트를 업로드하면 이 토큰도 함께 업로드됩니다.

요약

CI/CD 파이프라인은 공급망 침해의 주요 공격 표면이 되었습니다. 최신 소프트웨어 제공을 가능하게 하는 자동화는 공격자가 자격 증명을 수집하고 패키지를 포이즌하고 클라우드 인프라로 전환하는 데 악용하는 것과 동일합니다. 기존의 코드 리뷰는 이러한 패턴이 미묘하고 플랫폼에 따라 다르며 합법적인 DevOps 변경 사항처럼 보이도록 설계되어 있기 때문에 잘 포착하지 못합니다.

정규식 기반 신호 추출과 LLM 추론을 결합하면 이러한 패턴이 프로덕션에 도달하기 전에 풀 리퀘스트 단계에서 이러한 패턴을 파악할 수 있습니다. 리포지토리에는 전체 위협 모델, 테스트 스위트 및 세부 사항을 분석하거나 사용자 환경에 맞게 조정하려는 경우 예제 차이점이 포함되어 있습니다.

시작하려면 설정 지침, 전체 위협 모델 및 차이점 예시를 보려면 cicd-abuse-detector 리포지토리에서 확인하세요. 저희는 항상 새로운 공격 패턴과 탐지 아이디어에 대해 관심을 갖고 있습니다. 커뮤니티 Slack에서 채팅하고 토론 포럼에서 질문하세요.

MITRE ATT를 통한 CI/CD 악용&CK

저희는 공격자들이 CI/CD 파이프라인에 대해 사용하는 전술, 기법, 절차를 매핑하기 위해 MITRE ATT& CK 프레임워크를 사용합니다.

전술

전술CI/CD 관련성
자격 증명 액세스(TA0006)CI 환경에서 비밀 수집하기
실행(TA0002)파이프라인 러너에서 명령 실행
지속성(TA0003)예약된 트리거, 크론 기반 워크플로
방어 회피(TA0005)커밋 타임스탬프 조작, 로그 마스킹 회피
초기 액세스(TA0001)손상된 개발자 자격 증명, PAT 피싱
측면 이동(TA0008)수집된 클라우드 자격 증명을 사용하여 피벗하기

기술

기술CI/CD 애플리케이션
T1552: 보안되지 않은 자격증명CI 환경 변수, 아티팩트 및 런처 메모리에 노출된 비밀
T1195.002: 소프트웨어 공급망 손상포이즈드 액션, 종속성 및 잠금 파일
T1059: 명령 및 스크립팅 인터프리터curl
T1070.006: 타임스탬프검토를 피하기 위해 커밋 날짜를 뒤로 미루기
T1098: 계정 조작쓰기-모두를 통한 권한 에스컬레이션, ID 토큰: 쓰기
T1078: 유효한 계정워크플로우를 수정하는 데 사용된 도난당한 개발자 PAT

참고 자료

위의 조사에서 참조한 내용은 다음과 같습니다:

Elastic 보안 연구소 소개

Elastic Security Labs는 위협 환경에 긍정적인 변화를 일으키는 데 전념하는 Elastic Security의 위협 인텔리전스 부서입니다. Elastic Security Labs는 전략적, 운영적, 전술적 적의 목표에 대한 분석과 함께 새로운 위협에 대한 공개적으로 이용 가능한 연구를 제공한 다음, 이러한 연구를 Elastic Security의 기본 제공 탐지 및 대응 기능과 통합합니다.

트위터 @elasticseclabs를 팔로우하고 www.elastic.co/security-labs/ 에서 저희 연구 결과를 확인하세요.

이 문서 공유하기