의존성 혼동, 타이포스쿼팅, CI 침투 등 공급망 공격 유형을 분석하고, SLSA 프레임워크와 어드미션 컨트롤러 기반의 제로 트러스트 방어 전략을 구축합니다.
**Software Supply Chain Attack(소프트웨어 공급망 공격)**은 최종 타겟을 직접 공격하는 대신, 타겟이 의존하는 소프트웨어 구성 요소를 통해 침투하는 공격입니다.
현대 소프트웨어는 수백에서 수천 개의 오픈소스 패키지에 의존합니다. 이 의존성 체인의 어디든 공격자가 악성 코드를 삽입할 수 있다면, 그 패키지를 사용하는 모든 소프트웨어가 영향을 받습니다.
**Dependency Confusion(의존성 혼동)**은 공격자가 내부 패키지와 동일한 이름의 패키지를 퍼블릭 레지스트리에 등록하여, 빌드 시스템이 내부 패키지 대신 악성 패키지를 다운로드하도록 유도하는 공격입니다.
예를 들어 조직 내부에서 @mycompany/auth-utils라는 이름의 프라이빗 패키지를 사용한다고 가정합니다. 공격자가 npm 퍼블릭 레지스트리에 동일한 이름으로 더 높은 버전의 패키지를 등록하면, 패키지 매니저가 퍼블릭 버전을 우선 설치할 수 있습니다.
방어 방법:
@mycompany:registry=https://npm.mycompany.com/
//npm.mycompany.com/:_authToken=${NPM_TOKEN}npmScopes:
mycompany:
npmRegistryServer: "https://npm.mycompany.com/"
npmAuthToken: "${NPM_TOKEN}"내부 스코프를 프라이빗 레지스트리에 명시적으로 고정하면, 퍼블릭 레지스트리에서 동일 이름의 패키지를 가져오지 않습니다.
**Typosquatting(타이포스쿼팅)**은 인기 있는 패키지 이름과 유사한 이름으로 악성 패키지를 등록하는 공격입니다.
| 실제 패키지 | 악성 패키지 (예시) |
|---|---|
| lodash | lodahs, 1odash |
| express | expres, expresss |
| requests (Python) | request, requets |
방어 방법:
package-lock.json, pnpm-lock.yaml 등 잠금 파일(lockfile)을 반드시 커밋합니다.--frozen-lockfile 옵션으로 CI에서 잠금 파일과 다른 버전이 설치되는 것을 차단합니다.name: Dependency Review
on:
pull_request:
jobs:
dependency-review:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Dependency Review
uses: actions/dependency-review-action@v4
with:
fail-on-severity: moderate
deny-licenses: GPL-3.0, AGPL-3.0공격자가 CI/CD 시스템 자체를 타겟으로 삼는 공격입니다. 빌드 스크립트를 변조하거나, 빌드 환경에 악성 도구를 주입합니다.
대표적인 공격 벡터는 다음과 같습니다.
방어 방법:
steps:
# 나쁜 예: 태그만 사용 (언제든 변경 가능)
# - uses: actions/checkout@v4
# 좋은 예: 커밋 해시로 고정
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1서드파티 GitHub Actions를 사용할 때는 반드시 커밋 해시로 고정하세요. 태그는 악의적으로 변경될 수 있지만, 커밋 해시는 불변입니다. StepSecurity의 harden-runner와 같은 도구로 Action의 네트워크 활동을 모니터링하는 것도 효과적입니다.
5장에서 **SLSA(Supply chain Levels for Software Artifacts)**를 소개했습니다. 이번 장에서는 각 레벨의 구체적인 요구사항과 구현 방법을 심화하여 다룹니다.
| 레벨 | 빌드 요구사항 | 소스 요구사항 | 출처 증명 |
|---|---|---|---|
| L1 | 문서화된 빌드 | 버전 관리 | 기본 Provenance |
| L2 | 호스팅된 CI/CD | 버전 관리 | 서명된 Provenance |
| L3 | 격리된 빌드 | 2인 리뷰 | 검증 가능한 Provenance |
| L4 | 재현 가능 | 2인 리뷰 + 브랜치 보호 | 완전한 Provenance |
**Provenance(출처 증명)**는 "이 아티팩트가 어디서, 어떻게, 무엇으로 빌드되었는가"를 기록한 메타데이터입니다.
{
"_type": "https://in-toto.io/Statement/v1",
"subject": [
{
"name": "ghcr.io/myorg/myapp",
"digest": {
"sha256": "abc123..."
}
}
],
"predicateType": "https://slsa.dev/provenance/v1",
"predicate": {
"buildDefinition": {
"buildType": "https://github.com/slsa-framework/slsa-github-generator",
"externalParameters": {
"source": {
"uri": "git+https://github.com/myorg/myapp@refs/heads/main",
"digest": {
"sha1": "def456..."
}
}
}
},
"runDetails": {
"builder": {
"id": "https://github.com/slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@refs/tags/v2.0.0"
},
"metadata": {
"invocationId": "https://github.com/myorg/myapp/actions/runs/12345"
}
}
}
}# slsa-verifier로 출처 증명 검증
slsa-verifier verify-image \
ghcr.io/myorg/myapp@sha256:abc123... \
--source-uri github.com/myorg/myapp \
--source-branch main
# cosign으로 attestation 검증
cosign verify-attestation \
--type slsaprovenance \
--certificate-identity-regexp=".*slsa-framework/slsa-github-generator.*" \
--certificate-oidc-issuer="https://token.actions.githubusercontent.com" \
ghcr.io/myorg/myapp@sha256:abc123...**Admission Controller(어드미션 컨트롤러)**는 쿠버네티스 API 서버로 들어오는 요청을 가로채어 정책을 적용하는 메커니즘입니다. 이미지 정책, 서명 검증, SLSA 레벨 확인 등을 배포 시점에 강제할 수 있습니다.
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: container-security-policy
spec:
validationFailureAction: Enforce
rules:
# 규칙 1: 허용된 레지스트리만 사용
- name: restrict-registries
match:
any:
- resources:
kinds:
- Pod
validate:
message: "허용된 레지스트리의 이미지만 사용할 수 있습니다."
pattern:
spec:
containers:
- image: "ghcr.io/myorg/* | cgr.dev/chainguard/*"
# 규칙 2: latest 태그 금지
- name: deny-latest-tag
match:
any:
- resources:
kinds:
- Pod
validate:
message: "latest 태그는 사용할 수 없습니다. 구체적인 버전을 지정하세요."
pattern:
spec:
containers:
- image: "!*:latest"
# 규칙 3: 이미지 서명 검증
- name: verify-signature
match:
any:
- resources:
kinds:
- Pod
verifyImages:
- imageReferences:
- "ghcr.io/myorg/*"
attestors:
- entries:
- keyless:
subject: "https://github.com/myorg/*"
issuer: "https://token.actions.githubusercontent.com"
# 규칙 4: SLSA Provenance 검증
- name: verify-slsa-provenance
match:
any:
- resources:
kinds:
- Pod
verifyImages:
- imageReferences:
- "ghcr.io/myorg/*"
attestations:
- type: "https://slsa.dev/provenance/v1"
attestors:
- entries:
- keyless:
subject: "https://github.com/slsa-framework/*"
issuer: "https://token.actions.githubusercontent.com"
conditions:
- all:
- key: "{{ buildDefinition.externalParameters.source.uri }}"
operator: Equals
value: "git+https://github.com/myorg/*"이 정책은 네 가지 규칙을 한번에 적용합니다.
latest 태그 사용 금지정책을 처음 도입할 때는 validationFailureAction: Audit로 설정하여 모니터링 모드로 운영하세요. 기존 워크로드에 영향을 주지 않으면서 정책 위반 현황을 파악할 수 있습니다. 충분히 검증된 후에 Enforce로 전환합니다.
**Zero Trust(제로 트러스트)**는 "아무것도 신뢰하지 않고, 항상 검증한다"는 원칙입니다. 컨테이너 환경에서 제로 트러스트를 구현하려면 다음 계층 모두에서 검증이 이루어져야 합니다.
| 계층 | 검증 항목 | 도구 |
|---|---|---|
| 코드 | 의존성 리뷰, 2인 리뷰 | Dependency Review, Branch Protection |
| 빌드 | 격리 빌드, Provenance 생성 | SLSA GitHub Generator |
| 이미지 | 서명, SBOM, 취약점 스캔 | Cosign, Syft, Trivy |
| 배포 | 서명 검증, 정책 적용 | Kyverno, OPA Gatekeeper |
| 런타임 | 시스콜 모니터링, 행동 감지 | Falco |
| 네트워크 | 기본 거부, mTLS | Cilium, Istio |
| 접근 | RBAC, 시크릿 로테이션 | Vault, ESO |
공격자가 SolarWinds의 빌드 시스템에 침투하여 Orion 소프트웨어의 업데이트에 악성 코드를 삽입했습니다. 이 업데이트를 적용한 18,000여 조직이 영향을 받았습니다.
교훈: 빌드 시스템 자체의 보안이 중요하며, SLSA Level 3 이상의 격리된 빌드 환경이 이런 공격을 방지할 수 있습니다.
공격자가 Codecov의 Bash Uploader 스크립트를 변조하여 CI 환경의 환경 변수(시크릿 포함)를 외부로 유출했습니다.
교훈: CI/CD에서 실행하는 서드파티 스크립트와 Action의 무결성을 검증해야 하며, 해시 고정이 필수적입니다.
npm 패키지 event-stream의 유지 관리자가 악의적인 개발자에게 소유권을 이전했고, 해당 개발자가 암호화폐 지갑을 탈취하는 악성 코드를 삽입했습니다.
교훈: 오픈소스 패키지의 유지 관리자 변경을 모니터링하고, 의존성 업데이트를 자동으로 리뷰하는 체계가 필요합니다.
공급망 공격은 단일 방어선으로 막을 수 없습니다. 이 시리즈에서 다룬 모든 보안 계층 - 이미지 스캐닝, SBOM, 서명, 런타임 감지, 네트워크 정책 - 이 함께 동작해야 효과적인 방어가 가능합니다.
이번 장에서는 공급망 공격의 유형과 방어 전략을 다루었습니다.
다음 장에서는 이 시리즈에서 배운 모든 내용을 하나로 통합하는 실전 프로젝트를 수행합니다. 빌드부터 스캔, 서명, 배포, 런타임 모니터링까지 완전한 보안 파이프라인을 구축합니다.
이 글이 도움이 되셨나요?
빌드, 스캔, 서명, 배포, 런타임 모니터링까지 전체 컨테이너 보안 파이프라인을 GitHub Actions와 쿠버네티스 기반으로 통합 구축하는 실전 프로젝트입니다.
쿠버네티스 Secrets의 한계를 이해하고, HashiCorp Vault, External Secrets Operator, Sealed Secrets로 안전한 시크릿 관리 체계를 구축합니다.
쿠버네티스 NetworkPolicy로 기본 거부 정책을 구현하고, Calico/Cilium 네트워크 정책과 Istio mTLS로 컨테이너 간 통신을 안전하게 제어합니다.