CI/CD 보안 상위 10대 위험은 무엇입니까?

OWASP 상위 10대 CI/CD 보안 위험은 지속적인 통합 및 지속적인 전달 파이프라인에서 가장 중요한 보안 위험을 식별합니다. CI/CD 파이프라인은 소스 코드, 비밀 및 프로덕션 환경에 직접 액세스할 수 있기 때문에 가치가 높은 대상입니다. 이 가이드에서는 흐름 제어, ID 관리, 종속성 공격, 파이프라인 중독 등을 다룹니다.

1️⃣ CICD-SEC-1 - 불충분한 흐름 제어 메커니즘

Critical

개요

불충분한 흐름 제어 메커니즘으로 인해 공격자는 적절한 검토 또는 승인 게이트 없이 CI/CD 파이프라인을 통해 악성 코드를 푸시할 수 있습니다. 여기에는 분기 보호 규칙 우회, 필수 승인 누락, 프로덕션 배포를 트리거할 수 있는 사람에 대한 시행 부족 등이 포함됩니다.

위험

적절한 흐름 제어가 없으면 손상된 단일 개발자 계정이나 악의적인 내부자가 코드 검토, 보안 검색 및 승인 프로세스를 우회하여 코드를 프로덕션에 직접 푸시할 수 있습니다. 이로 인해 백도어, 데이터 유출 코드 또는 파괴적인 페이로드가 배포될 수 있습니다.

취약한 코드 예

YAML (GitHub Actions) ❌ Bad
# No branch protection — anyone can push directly to main
name: Deploy
on:
  push:
    branches: [main]  # Triggers on any push to main
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - run: |
        # Deploys immediately — no approval gate!
        kubectl apply -f deploy.yaml
        kubectl rollout status deployment/myapp

보안 코드 예

YAML (GitHub Actions) ✅ Good
name: Deploy
on:
  push:
    branches: [main]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - run: npm test
  deploy:
    needs: test
    runs-on: ubuntu-latest
    environment: production  # Requires manual approval
    steps:
    - uses: actions/checkout@v4
    - run: |
        kubectl apply -f deploy.yaml
        kubectl rollout status deployment/myapp

완화 체크리스트

2️⃣ CICD-SEC-2 - 부적절한 ID 및 액세스 관리

Critical

개요

CI/CD 시스템에는 인간 사용자, 서비스 계정, 봇 토큰, 머신 ID 등 여러 ID가 포함됩니다. 부적절한 IAM은 리포지토리, 파이프라인 및 배포 대상에 대한 과도한 액세스를 허용합니다. 공유 자격 증명, 오래된 계정, MFA 부족으로 인해 위험이 가중됩니다.

위험

과도한 권한이 있는 손상된 CI/CD ID는 파이프라인을 수정하고, 비밀에 액세스하고, 빌드 아티팩트를 변경하고, 프로덕션에 배포할 수 있습니다. 공유 서비스 계정을 사용하면 누가 작업을 수행했는지 감사할 수 없습니다.

취약한 코드 예

YAML (GitHub Actions) ❌ Bad
# Over-permissive workflow with admin token
name: CI
on: push
permissions: write-all  # Full permissions to everything!
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - run: |
        # Using org-wide PAT with admin access
        curl -H "Authorization: token ${{ secrets.ADMIN_PAT }}" \
          https://api.github.com/repos/org/other-repo/contents/

보안 코드 예

YAML (GitHub Actions) ✅ Good
name: CI
on: push
permissions:
  contents: read    # Minimum required permissions
  packages: write   # Only what's needed
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - uses: actions/create-github-app-token@v1  # Scoped app token
      id: app-token
      with:
        app-id: ${{ vars.APP_ID }}
        private-key: ${{ secrets.APP_PRIVATE_KEY }}
        repositories: other-repo  # Scoped to specific repo

완화 체크리스트

3️⃣ CICD-SEC-3 - 종속성 체인 남용

Critical

개요

CI/CD 파이프라인은 외부 패키지 레지스트리(npm, PyPI, Maven, Docker Hub)에서 종속성을 가져옵니다. 공격자는 종속성 혼란, 타이포스쿼팅, 손상된 관리자 계정 및 악성 패키지를 통해 이를 악용합니다. 단일 중독 종속성은 빌드 중에 임의의 코드를 실행할 수 있습니다.

위험

악성 종속성은 설치(설치 후 스크립트, setup.py) 중에 코드를 실행하고, 비밀을 도용하고, 빌드 아티팩트에 백도어를 삽입하거나 지속성을 설정합니다. SolarWinds 및 Codecov와 같은 공급망 공격은 치명적인 영향을 보여줍니다.

취약한 코드 예

Jenkinsfile ❌ Bad
pipeline {
  agent any
  stages {
    stage('Build') {
      steps {
        // No lockfile verification, no integrity checks
        sh 'npm install'           // Fetches latest — could be compromised!
        sh 'pip install -r requirements.txt'  // No hash verification
      }
    }
  }
}

보안 코드 예

Jenkinsfile ✅ Good
pipeline {
  agent any
  stages {
    stage('Build') {
      steps {
        // Use lockfile with integrity verification
        sh 'npm ci'                   // Uses package-lock.json
        sh 'npm audit --audit-level=high'
        // Python: verify hashes from lockfile
        sh 'pip install --require-hashes -r requirements.lock'
      }
    }
    stage('SCA Scan') {
      steps {
        // Software Composition Analysis
        sh 'trivy fs --scanners vuln,secret .'
      }
    }
  }
}

완화 체크리스트

4️⃣ CICD-SEC-4 - 중독된 파이프라인 실행(PPE)

Critical

개요

PPE(Poisoned Pipeline Execution)는 공격자가 CI/CD 파이프라인 정의를 수정하거나 파이프라인 컨텍스트 내에서 실행되는 악성 코드를 삽입할 수 있을 때 발생합니다. 이는 브랜치의 파이프라인 구성 파일 조작, 포크의 풀 요청 또는 공유 파이프라인 템플릿 수정을 통해 발생할 수 있습니다.

위험

파이프라인 구성을 수정할 수 있는 공격자는 파이프라인에 사용 가능한 모든 비밀, 자격 증명 및 권한에 대한 액세스 권한을 얻습니다. 신뢰할 수 있는 실행 컨텍스트 내에서 비밀을 유출하거나, 빌드 출력을 조작하거나, 악성 코드를 배포할 수 있습니다.

취약한 코드 예

YAML (GitHub Actions) ❌ Bad
# Runs pipeline from fork PRs with access to secrets
name: CI
on:
  pull_request_target:  # Runs in base repo context with secrets!
    branches: [main]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
      with:
        ref: ${{ github.event.pull_request.head.sha }}  # Checks out fork code!
    - run: make build  # Fork's Makefile executes with secrets access
      env:
        DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }}

보안 코드 예

YAML (GitHub Actions) ✅ Good
# Separate workflows: untrusted build + trusted deploy
name: CI
on:
  pull_request:  # No secret access for PR builds
    branches: [main]
permissions:
  contents: read
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4  # Checks out merge commit (safe)
    - run: npm ci && npm test   # No secrets needed for build/test
    - uses: actions/upload-artifact@v4
      with:
        name: build-output
        path: dist/

완화 체크리스트

5️⃣ CICD-SEC-5 - 불충분한 파이프라인 기반 액세스 제어(PBAC)

High

개요

PBAC(파이프라인 기반 액세스 제어)는 파이프라인이 액세스할 수 있는 리소스(클라우드 계정, Kubernetes 클러스터, 데이터베이스, 내부 서비스)를 제어합니다. PBAC가 충분하지 않다는 것은 파이프라인이 필요한 것보다 더 광범위한 액세스 권한을 가지며 최소 권한 원칙을 위반한다는 것을 의미합니다.

위험

과도한 권한이 부여된 파이프라인을 활용하여 의도한 범위를 훨씬 넘어서는 리소스에 액세스할 수 있습니다. 사소한 서비스에 대해 손상된 빌드 파이프라인을 사용하여 프로덕션 데이터베이스에 액세스하거나, 인프라를 수정하거나, 다른 환경으로 전환할 수 있습니다.

취약한 코드 예

YAML (GitLab CI) ❌ Bad
# Pipeline with admin-level cloud credentials
deploy:
  stage: deploy
  script:
    - aws configure set aws_access_key_id $AWS_ACCESS_KEY
    - aws configure set aws_secret_access_key $AWS_SECRET_KEY
    # This key has AdministratorAccess policy!
    - aws s3 sync dist/ s3://my-bucket/
    - aws ecs update-service --cluster prod --service myapp
    # Same credentials could access ANY AWS resource

보안 코드 예

YAML (GitHub Actions) ✅ Good
name: Deploy
on:
  push:
    branches: [main]
permissions:
  id-token: write  # For OIDC
  contents: read
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
    - uses: aws-actions/configure-aws-credentials@v4
      with:
        role-to-assume: arn:aws:iam::123456:role/deploy-s3-only
        # Scoped role: only s3:PutObject on specific bucket
        aws-region: us-east-1
    - run: aws s3 sync dist/ s3://my-bucket/

완화 체크리스트

6️⃣ CICD-SEC-6 - 자격 증명 위생이 불충분함

Critical

개요

CI/CD 파이프라인은 API 키, 클라우드 토큰, 레지스트리 비밀번호, SSH 키, 서명 인증서 등 다양한 자격 증명을 처리합니다. 열악한 자격 증명 위생에는 파이프라인 파일의 비밀 하드코딩, 로그에 비밀 인쇄, 암호화되지 않은 비밀 저장소 사용, 자격 증명 절대 교체 등이 포함됩니다.

위험

유출된 CI/CD 자격 증명은 가장 일반적인 초기 액세스 벡터 중 하나입니다. 빌드 로그에 노출되거나 리포지토리에 커밋되거나 암호화 없이 저장된 비밀은 공격자에게 프로덕션 시스템, 클라우드 계정 및 아티팩트 레지스트리에 직접 액세스할 수 있는 권한을 제공합니다.

취약한 코드 예

Bash (CI Script) ❌ Bad
#!/bin/bash
# Secrets hardcoded and leaked in logs
export DOCKER_PASSWORD="MyS3cret!"         # Hardcoded!
echo "Logging in with $DOCKER_PASSWORD"  # Printed to logs!

docker login -u admin -p "$DOCKER_PASSWORD" registry.example.com
docker push registry.example.com/myapp:latest

# AWS credentials in environment — visible in process listing
export AWS_SECRET_ACCESS_KEY="wJalrXUtnFEMI/K7MDENG/bPxRfiCY"
aws s3 cp artifact.zip s3://releases/

보안 코드 예

YAML (GitHub Actions) ✅ Good
name: Publish
on:
  push:
    tags: ['v*']
jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - uses: docker/login-action@v3  # Handles credentials securely
      with:
        registry: registry.example.com
        username: ${{ secrets.DOCKER_USER }}   # Masked in logs
        password: ${{ secrets.DOCKER_TOKEN }}  # Short-lived token
    - run: |
        docker build -t registry.example.com/myapp:${{ github.ref_name }} .
        docker push registry.example.com/myapp:${{ github.ref_name }}

완화 체크리스트

7️⃣ CICD-SEC-7 - 안전하지 않은 시스템 구성

High

개요

CI/CD 시스템(Jenkins, GitLab, GitHub Actions 러너)은 안전하지 않은 기본 구성으로 실행되는 경우가 많습니다. 여기에는 오래된 소프트웨어 버전, 노출된 관리 인터페이스, 비활성화된 보안 기능, 과도한 네트워크 액세스 및 프로젝트 전체에서 공유되는 자체 호스팅 실행기가 포함됩니다.

위험

잘못 구성된 CI/CD 인프라를 악용하여 환경 구축에 대한 무단 액세스 권한을 얻거나, 비밀을 가로채거나, 내부 네트워크로 전환할 수 있습니다. 공유된 자체 호스팅 실행기는 하나의 손상된 워크플로가 다른 워크플로에 영향을 미치는 프로젝트 간 공격을 허용합니다.

취약한 코드 예

Groovy (Jenkins) ❌ Bad
// Jenkins with insecure configuration
// - Script console enabled without auth
// - Agent-to-controller access unrestricted
// - Outdated plugins with known CVEs

pipeline {
  agent any  // Runs on any available agent — no isolation
  stages {
    stage('Build') {
      steps {
        // Running as root on shared agent
        sh 'whoami'  // root
        sh 'docker build -t myapp .'
      }
    }
  }
}

보안 코드 예

Groovy (Jenkins) ✅ Good
pipeline {
  agent {
    kubernetes {  // Ephemeral, isolated pod per build
      yaml """
        apiVersion: v1
        kind: Pod
        spec:
          securityContext:
            runAsNonRoot: true
            runAsUser: 1000
          containers:
          - name: builder
            image: builder:1.2.3
            securityContext:
              allowPrivilegeEscalation: false
              readOnlyRootFilesystem: true
      """
    }
  }
  stages {
    stage('Build') {
      steps {
        container('builder') {
          sh 'make build'
        }
      }
    }
  }
}

완화 체크리스트

8️⃣ CICD-SEC-8 - 제3자 서비스의 통제되지 않은 사용

High

개요

CI/CD 파이프라인은 코드 품질 도구, 보안 스캐너, 알림 시스템, 배포 플랫폼 등 타사 서비스와 통합되는 경우가 많습니다. 이러한 통합에는 액세스 토큰 및 권한이 부여되어 신뢰 체인이 생성됩니다. 관리되지 않는 사용은 타사 서비스가 액세스하거나 수행할 수 있는 작업에 대한 가시성이 없음을 의미합니다.

위험

Codecov 위반과 같은 손상된 타사 서비스는 소스 코드, 비밀 및 빌드 아티팩트에 액세스할 수 있습니다. 거버넌스 없이 팀은 알 수 없는 서비스에 과도한 권한을 부여하여 공급망에 보이지 않는 공격 벡터를 만들 수 있습니다.

취약한 코드 예

YAML (GitHub Actions) ❌ Bad
name: CI
on: push
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - run: npm test
    # Unknown third-party action with full repo access
    - uses: random-org/code-analysis@main  # Unpinned, unvetted!
      with:
        token: ${{ secrets.GITHUB_TOKEN }}   # Full token access!
    # Uploading coverage to external service with repo token
    - run: |
        bash <(curl -s https://example.com/uploader.sh)  # Remote script!

보안 코드 예

YAML (GitHub Actions) ✅ Good
name: CI
on: push
permissions:
  contents: read
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - run: npm test
    # Vetted action pinned to SHA
    - uses: github/codeql-action/analyze@8a470fddafa5cbc14  # Pinned SHA
    # Upload via official CLI tool, not remote scripts
    - uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673
      with:
        token: ${{ secrets.CODECOV_TOKEN }}  # Scoped token
        fail_ci_if_error: true

완화 체크리스트

9️⃣ CICD-SEC-9 - 부적절한 아티팩트 무결성 검증

High

개요

빌드 아티팩트(컨테이너 이미지, 바이너리, 패키지)는 CI/CD 파이프라인을 통해 프로덕션으로 흐릅니다. 무결성 검증이 없으면 빌드 중, 전송 중, 아티팩트 레지스트리 또는 배포 시 어느 시점에서든 아티팩트가 변조될 수 있습니다. 이는 코드에서 프로덕션까지 신뢰 체인을 깨뜨립니다.

위험

변조된 아티팩트에는 백도어, 악성 코드 또는 수정된 논리가 포함될 수 있습니다. 서명 및 확인 없이는 빌드 후 아티팩트가 수정되었는지 여부를 감지할 방법이 없습니다. 공격자는 레지스트리의 합법적인 이미지를 교체하거나 전송 중인 아티팩트를 가로챌 수 있습니다.

취약한 코드 예

Bash ❌ Bad
#!/bin/bash
# Build and deploy without any integrity checks
docker build -t myregistry.com/app:latest .
docker push myregistry.com/app:latest

# On deployment side — no verification
docker pull myregistry.com/app:latest  # Could be tampered!
docker run myregistry.com/app:latest   # Tag is mutable!

보안 코드 예

YAML (GitHub Actions) ✅ Good
name: Build and Sign
on:
  push:
    tags: ['v*']
permissions:
  id-token: write
  packages: write
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - run: |
        # Build with immutable tag (SHA)
        docker build -t myregistry.com/app:${{ github.sha }} .
        docker push myregistry.com/app:${{ github.sha }}
    - uses: sigstore/cosign-installer@v3
    - run: |
        # Sign image with keyless signing (Sigstore)
        cosign sign myregistry.com/app:${{ github.sha }}
        # Generate and attach SBOM
        syft myregistry.com/app:${{ github.sha }} -o spdx-json > sbom.json
        cosign attest --predicate sbom.json myregistry.com/app:${{ github.sha }}

완화 체크리스트

🔟 CICD-SEC-10 - 불충분한 로깅 및 가시성

Medium

개요

CI/CD 환경은 파이프라인 실행, 구성 변경, 비밀 액세스, 배포 활동 등 중요한 보안 이벤트를 생성합니다. 포괄적인 로깅 및 모니터링이 없으면 파이프라인의 악의적인 활동이 감지되지 않고 사고 대응이 심각하게 방해받습니다.

위험

CI/CD 활동에 대한 가시성이 없으면 공격자는 경고를 트리거하지 않고도 파이프라인을 수정하고, 비밀을 유출하고, 아티팩트를 변조할 수 있습니다. 감사 추적이 부족하면 위반의 범위와 영향을 판단하는 것이 불가능합니다.

취약한 코드 예

Bash ❌ Bad
#!/bin/bash
# Pipeline with no logging or audit trail
echo "Starting deployment..."
kubectl apply -f deploy.yaml
echo "Done."

# No record of: who triggered this, what changed,
# which image was deployed, what secrets were accessed
# Build logs expire after 30 days with no archival

보안 코드 예

YAML (GitHub Actions) ✅ Good
name: Audited Deploy
on:
  push:
    branches: [main]
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - name: Log deployment metadata
      run: |
        echo "=== Deployment Audit Log ==="
        echo "Triggered by: ${{ github.actor }}"
        echo "Commit: ${{ github.sha }}"
        echo "Ref: ${{ github.ref }}"
        echo "Workflow: ${{ github.workflow }}"
        echo "Run ID: ${{ github.run_id }}"
    - name: Deploy with audit
      run: |
        kubectl apply -f deploy.yaml 2>&1 | tee deploy.log
        # Send audit event to SIEM
        curl -X POST "${{ secrets.SIEM_WEBHOOK }}" \
          -d '{"event":"deploy","actor":"${{ github.actor }}","sha":"${{ github.sha }}"}'

완화 체크리스트

📊 요약표

ID 취약점 심각성 주요 완화
CICD-SEC-1불충분한 흐름 제어 메커니즘Critical지점 보호, 필수 승인, 환경 게이트
CICD-SEC-2부적절한 ID 및 액세스 관리Critical최소 권한 토큰, OIDC, MFA, 자격 증명 순환
CICD-SEC-3종속성 체인 남용Critical잠금 파일, 해시 확인, 개인 레지스트리, SCA
CICD-SEC-4중독된 파이프라인 실행(PPE)Critical별도의 빌드/배포, 불변 파이프라인 정의, 포크 제어
CICD-SEC-5PBAC가 부족함HighOIDC 페더레이션, 범위가 지정된 IAM 역할, 환경 분리
CICD-SEC-6불충분한 자격 증명 위생Critical비밀관리, 로그마스킹, 순환, 비밀스캐닝
CICD-SEC-7안전하지 않은 시스템 구성High임시 실행자, 루트가 아닌 사용자, 플러그인 업데이트, 네트워크 격리
CICD-SEC-8제3자 서비스의 통제되지 않은 사용High서비스 인벤토리, SHA 고정, 원격 스크립트 없음
CICD-SEC-9부적절한 아티팩트 무결성 검증High공동 서명, 승인 관리, SLSA 출처
CICD-SEC-10불충분한 로깅 및 가시성Medium감사 로깅, SIEM 통합, 경고, 로그 보존