독극물 파이프라인 실행(PPE)이란 무엇인가요?
OWASP CI/CD 보안 위험인 포이즌 파이프라인 실행(PPE)은 소스 코드 관리(SCM) 시스템에 대한 액세스 권한을 악용하여 CI 파이프라인이 악성 명령을 실행하도록 하는 공격 벡터입니다. PPE 공격자는 빌드 환경에는 액세스할 수 없지만 SCM에 액세스할 수 있으므로 빌드 파이프라인 구성에 악성 코드를 삽입하여 빌드 프로세스를 조작할 수 있습니다.
CICD-SEC-4: 중독된 파이프라인 실행 설명
OWASP 상위 10대 CI/CD 보안 위험에 CICD-SEC-4로 등재된 포이즌 파이프라인 실행(PPE)은 지속적인 통합 및 지속적인 구축(CI/CD) 시스템을 노리는 정교한 공격 전략을 나타냅니다.
고객은 다양한 옵션을 사용할 수 있습니다:
PPE 전략에서 공격자는 CI/CD 파이프라인의CI 부분 내에서 악성 코드를 실행하여 CI/CD 시스템에 직접 액세스하지 않고 우회합니다. 이 방법은 소스 코드 관리(SCM) 리포지토리에 대한 권한을 조작하는 것입니다. 공격자는 CI 구성 파일 또는 CI 파이프라인 작업이 의존하는 기타 파일을 변경함으로써 악성 명령을 주입하여 CI 파이프라인을 효과적으로 오염시키고 무단 코드 실행을 가능하게 합니다.
PPE 공격이 성공하면 파이프라인의 신원 컨텍스트 내에서 실행되는 광범위한 작업을 수행할 수 있습니다. 악의적인 작업에는 CI 작업에 사용할 수 있는 비밀에 액세스하고, 작업 노드에 권한이 있는 외부 자산에 액세스하고, 겉보기에 합법적인 코드와 아티팩트를 파이프라인으로 전송하고, 작업 노드의 네트워크 또는 환경에 있는 추가 호스트 및 자산에 액세스하는 것이 포함될 수 있습니다.
중대한 영향력, 낮은 탐지 가능성, 다양한 익스플로잇 기법의 존재를 고려할 때 PPE 공격은 광범위한 위협이 되고 있습니다. 보안 팀, 엔지니어 및 레드 팀원에게 PPE와 그 대응책을 이해하는 것은CI/CD 보안에매우 중요합니다.
파이프라인 실행 정의
지속적 통합(CI)의 맥락에서 파이프라인 실행 흐름은 파이프라인이 빌드하는 리포지토리에 호스팅된 CI 구성 파일에 정의된 작업 순서를 의미합니다. 이 파일에는 실행되는 작업의 순서와 흐름에 영향을 미치는 빌드 환경 설정 및 조건이 자세히 설명되어 있습니다. 트리거되면 파이프라인 작업은 선택한 소스(예: 커밋/브랜치)에서 코드를 가져오고 해당 코드에 대해 CI 구성 파일에 지정된 명령을 실행합니다.
파이프라인 내의 명령은 CI 구성 파일에 의해 직접 호출되거나 CI 구성 파일에서 참조되는 별도의 파일에 있는 스크립트, 코드 테스트 또는 린터에 의해 간접적으로 호출됩니다. CI 구성 파일은 일반적으로 Jenkinsfile(Jenkins), .gitlab-ci.yml(GitLab), .circleci/config.yml(CircleCI), .github/workflows 아래에 있는 GitHub Actions YAML 파일 등 이름과 형식이 일관적입니다.
공격자는 파이프라인에서 실행되는 명령을 직접 또는 간접적으로 조작하는 기능을 악용하여 CI에서 악성 코드를 실행할 수 있습니다.
CICD-SEC-4의 악용이 발생하는 방식
PPE 공격이 성공하려면 몇 가지 기준을 충족해야 합니다:
- 공격자는 SCM 리포지토리에 대한 권한을 얻어야 합니다. 이는 사용자 자격 증명, 액세스 토큰, SSH 키, OAuth 토큰 또는 기타 방법을 통해 이루어질 수 있습니다. 경우에 따라서는 공용 리포지토리에 대한 익명 액세스로 충분할 수도 있습니다.
- 해당 리포지토리에 대한 변경 사항은 추가 승인이나 검토 없이 CI 파이프라인을 트리거해야 합니다. 원격 브랜치에 직접 푸시하거나 원격 브랜치 또는 포크에서 풀 리퀘스트를 통해 제안된 변경 사항을 통해 푸시할 수 있습니다.
- 공격자가 획득한 권한은 파이프라인을 실행하게 하는 이벤트를 트리거할 수 있어야 합니다.
- 공격자가 변경할 수 있는 파일은 파이프라인에서 직접 또는 간접적으로 실행되는 명령을 정의해야 합니다.
- 파이프라인 노드는 시크릿, 다른 노드 또는 컴퓨팅 리소스와 같은 비공개 리소스에 대한 액세스 권한이 있어야 합니다.
풀 리퀘스트나 임의의 리포지토리 브랜치에 대한 커밋과 같이 검토되지 않은 코드를 실행하는 파이프라인은 PPE에 더 취약합니다. 공격자가 CI 파이프라인 내에서 악성 코드를 실행할 수 있게 되면 파이프라인의 신원 컨텍스트 내에서 악의적인 작업을 수행할 수 있습니다.
포이즌 파이프라인 실행의 세 가지 유형
중독된 파이프라인 실행은 직접 PPE(D-PPE), 간접 PPE(I-PPE), 공공 PPE(3PE)의 세 가지 형태로 나타납니다.
직접 PPE
직접 PPE 시나리오에서 공격자는 리포지토리의 보호되지 않은 원격 브랜치에 직접 변경 사항을 푸시하거나 브랜치 또는 포크에서 변경 사항이 포함된 풀 리퀘스트를 제출하여 자신이 액세스할 수 있는 리포지토리의 CI 구성 파일을 수정합니다. 파이프라인 실행은 수정된 CI 구성 파일의 명령에 정의된 대로 푸시 또는 풀 요청 이벤트에 의해 트리거되며, 빌드 파이프라인이 트리거되면 빌드 노드에서 악의적인 명령이 실행됩니다.

그림 1: 직접 중독된 파이프라인 실행 공격 흐름
그림 1에 설명된 D-PPE 공격 예시는 다음과 같은 일련의 단계를 거쳐 발생합니다:
- 공격자는 리포지토리 내에서 새로운 원격 브랜치를 시작하여 파이프라인 구성 파일을 유해한 지침으로 변경하여 GitHub 조직 내에 저장된 AWS 자격 증명을 검색하고 공격자의 제어하에 있는 외부 서버로 전송합니다.
- 코드 푸시는 리포지토리에서 악성 파이프라인 구성 파일을 포함한 코드를 가져오는 파이프라인을 활성화합니다.
- 파이프라인은 이제 공격자에 의해 오염된 구성 파일에 따라 작동합니다. 악성 명령은 리포지토리 비밀로 저장된 AWS 자격 증명을 메모리에 로드하도록 명령합니다.
- 공격자의 지시에 따라 파이프라인은 공격자의 통제 하에 있는 서버로 AWS 자격 증명을 전송하는 작업을 수행합니다.
- 공격자는 탈취한 자격 증명을 통해 프로덕션 환경에 침투할 수 있는 능력을 얻게 됩니다.
간접 PPE
간접 PPE는 SCM 리포지토리에 액세스할 수 있는 공격자가 D-PPE를 사용할 수 없는 경우에 발생합니다:
- 파이프라인이 동일한 리포지토리에 있는 별도의 보호된 브랜치에서 CI 구성 파일을 가져오도록 구성된 경우.
- CI 구성 파일이 소스 코드와 별도의 리포지토리에 저장되어 있고 사용자가 직접 편집할 수 있는 옵션이 없는 경우.
- CI 빌드가 소스 코드에 저장된 파일이 아닌 CI 시스템 자체에 정의되어 있는 경우.
이러한 시나리오에서도 공격자는 파이프라인 구성 파일 내에서 참조하는 스크립트, 코드 테스트, CI에 사용되는 린터 및 보안 스캐너와 같은 자동 도구 등 파이프라인 구성 파일에서 참조하는 파일에 악성 코드를 주입하여 파이프라인을 오염시킬 수 있습니다. 예를 들어
- make 유틸리티는 메이크파일 파일에 정의된 명령을 실행합니다.
- 파이프라인 구성 파일 내에서 참조되는 스크립트로, 소스 코드 자체와 동일한 리포지토리에 저장됩니다(예: 파이썬 myscript.py - 공격자가 myscript.py를 조작할 수 있는 곳).
- 코드 테스트: 빌드 프로세스 내에서 애플리케이션 코드에서 실행되는 테스트 프레임워크는 소스 코드와 동일한 리포지토리에 저장된 전용 파일에 의존합니다. 테스트를 담당하는 코드를 조작할 수 있는 공격자는 빌드 내부에서 악의적인 명령을 실행할 수 있습니다.
- 자동 도구: CI에 사용되는 린터와 보안 스캐너는 일반적으로 리포지토리에 있는 구성 파일에 의존하며, 일반적으로 구성 파일 내부에 정의된 위치에서 외부 코드를 로드하고 실행합니다.
공격자는 직접 PPE를 통해 파이프라인을 오염시키는 대신 구성 파일에서 참조하는 파일에 악성 코드를 삽입하는 간접 PPE 공격을 시작합니다. 악성 코드는 최종적으로 파이프라인 노드에서 실행되며 파일에 선언된 명령을 실행합니다.

그림 2: 간접적으로 중독된 파이프라인 실행 공격 흐름
이 I-PPE 공격 예시에서 일련의 사건은 다음과 같이 전개됩니다:
- 공격자는 리포지토리에 풀 리퀘스트를 생성하여 Makefile 파일에 악성 명령을 추가합니다.
- 파이프라인은 리포지토리에 대한 모든 PR에서 트리거되도록 구성되어 있기 때문에 Jenkins 파이프라인이 트리거되어 리포지토리에서 악성 메이크파일을 포함한 코드를 가져옵니다.
- 파이프라인은 메인 브랜치에 저장된 구성 파일을 기반으로 실행됩니다. 빌드 단계에 도달하면 원래 Jenkins파일에 정의된 대로 AWS 자격 증명을 환경 변수에 로드합니다. 그런 다음 메이크파일에 추가한 악성 명령을 실행하는 make build 명령을 실행합니다.
- 메이크파일에 정의된 악성 빌드 함수가 실행되어 공격자가 제어하는 서버로 AWS 자격 증명을 전송합니다.
- 그러면 공격자는 탈취한 자격 증명을 사용하여 AWS 프로덕션 환경에 액세스할 수 있습니다.
공공 PPE
공개 PPE는 익명의 공격자가 인터넷에서 실행하는 PPE 공격의 한 유형입니다. 공개 리포지토리는 보통 풀 리퀘스트를 생성하여 모든 사용자가 기여할 수 있도록 허용합니다. 공개 리포지토리의 CI 파이프라인이 익명의 사용자가 제안한 검토되지 않은 코드를 실행하는 경우, 공개 PPE 공격에 노출될 수 있습니다. 또한 취약한 공용 저장소의 파이프라인이 비공개 저장소와 동일한 CI 인스턴스에서 실행되는 경우, 비공개 프로젝트의 기밀과 같은 내부 자산이 노출될 수도 있습니다.
CI/CD에서 안전한 파이프라인 실행의 중요성
성공적인 PPE 공격을 통해 CI에서 검토되지 않은 악성 코드를 실행하면 공격자는 빌드 작업과 동일한 수준의 액세스 권한과 기능을 갖게 됩니다:
- 환경 변수로 주입된 비밀 또는 CI에 저장된 추가 비밀과 같이 CI 작업에 사용할 수 있는 비밀에 대한 액세스 권한입니다. 코드 구축 및 아티팩트 구축을 담당하는 CI/CD 시스템에는 일반적으로 클라우드 공급자, 아티팩트 레지스트리, SCM 자체 등 수십 개의 고가치 크리덴셜과 토큰이 포함되어 있습니다.
- 노드의 파일 시스템에 저장된 파일 또는 기본 호스트를 통해 액세스할 수 있는 클라우드 환경에 대한 자격 증명 등 작업 노드에 권한이 있는 외부 자산에 대한 액세스 권한입니다.
- 빌드 프로세스에서 빌드된 합법적인 코드로 가장하여 코드와 아티팩트를 파이프라인 아래로 더 내려보낼 수 있습니다.
- 작업 노드의 네트워크/환경에서 추가 호스트 및 자산에 액세스할 수 있습니다.
그러나 조직은 컴파일, 테스트, 구축된 모든 코드가 합법적이고 변조되지 않도록 보장하는 보안 파이프라인 실행을 통해 소프트웨어 제품 및 인프라를 보호할 수 있습니다.
중독된 파이프라인 실행과 관련된 위험
무단 데이터 액세스, 소프트웨어 무결성 손상, 시스템 중단, 데이터 유출 또는 전체 시스템 탈취에 이르기까지 PPE가 미치는 영향은 심각할 수 있습니다. 이러한 위험은 비즈니스와 고객 모두에게 심각한 위협이 되며, 이는 개인보호장비의 심각성을 강조합니다.

그림 3: 오염된 CI 파이프라인의 다운스트림 영향
그림 3에서 볼 수 있는 8단계 공급망 침해 작업에서 공격자는 CI 파이프라인에 액세스하여 SaaS 애플리케이션의 구성 요소를 독살합니다. 공격자는 포이즌된 구성 요소를 통해 애플리케이션에 백도어 기능을 구축하고 포이즌된 플러그인을 다운스트림 클라이언트로 전송합니다. 다운스트림 조직은 포이즌 패키지를 합법적인 것으로 인식할 가능성이 높기 때문에 클라우드 또는 온프레미스 인프라에 구축합니다.
공격자는 하나의 오염된 CI 파이프라인을 통해 수많은 조직에 백도어 접속 권한을 생성하여 기하급수적인 부수적 피해를 입힙니다. 솔라윈즈 공격이 바로 이런 경우였습니다.
자세히 보기: CI/CD 파이프라인 공격의 해부학
포이즌 파이프라인 실행 방지
PPE 공격 벡터를 예방하고 완화하려면 SCM 및 CI 시스템 전반에 걸친 여러 조치를 취해야 합니다:
- 검토되지 않은 코드를 실행하는 파이프라인이 격리된 노드에서 실행되는지, 아니면 기밀 및 민감한 환경에 노출되는지 확인하세요.
- 외부 기여자의 공개 리포지토리에 대한 파이프라인 트리거 필요성을 평가합니다. 가능하면 포크에서 시작된 파이프라인 실행을 자제하고 파이프라인 실행 시 수동 승인을 요구하는 등의 제어 기능을 추가하는 것을 고려하세요.
- 민감한 파이프라인(예: 시크릿에 노출된 파이프라인)의 경우 CI 시스템에서 파이프라인을 트리거하도록 구성된 각 브랜치가 SCM에서 상호연관되는 브랜치 보호 규칙을 가지고 있는지 확인하세요.
- 파이프라인에서 악성 코드를 실행하기 위한 CI 구성 파일의 조작을 방지하려면 파이프라인이 실행되기 전에 각 CI 구성 파일을 검토해야 합니다. 또는 파이프라인에서 빌드 중인 코드가 포함된 브랜치와는 별도로 원격 브랜치에서 CI 구성 파일을 관리할 수도 있습니다. 원격 지점은 보호됨으로 구성해야 합니다.
- 필요하지 않은 사용자로부터 SCM 리포지토리에 부여된 권한을 제거하세요.
- 각 파이프라인은 해당 목적을 달성하는 데 필요한 자격 증명에만 액세스할 수 있어야 합니다. 자격 증명에는 최소 요구 사항이 있는 권한이 있어야 합니다.