클라우드 네이티브 애플리케이션의 가장 중요한 보안 위험 10가지와 이를 완화하는 방법을 알아보세요.
OWASP 클라우드 네이티브 애플리케이션 보안 톱 10은 쿠버네티스, 도커, 서버리스 아키텍처와 같은 플랫폼에서 실행되는 클라우드 네이티브 애플리케이션의 가장 두드러진 보안 위험을 식별합니다. 여기에는 전체 클라우드 네이티브 스택에 걸쳐 잘못된 구성, 공급망 위험, 기밀 관리 등이 포함됩니다.
잘못 구성된 클라우드 서비스, 컨테이너, 오케스트레이터는 클라우드 네이티브 침해의 주요 원인입니다. 여기에는 컨테이너를 루트로 실행하거나, 기본 구성을 사용하거나, Kubernetes API 서버를 공개적으로 노출하거나, 클라우드 리소스에 대한 감사 로깅을 활성화하지 않은 경우 등이 포함됩니다.
공격자는 잘못된 구성을 악용하여 클러스터를 완전히 제어하거나, 컨테이너를 탈출하거나, 클라우드 메타데이터 서비스에 액세스하거나, 인프라 전반을 피벗할 수 있습니다. 잘못 구성된 하나의 S3 버킷이나 개방형 Kubernetes 대시보드로 인해 대규모 데이터 유출이 발생하기도 합니다.
# Running container as root with no resource limits FROM ubuntu:latest RUN apt-get update && apt-get install -y curl wget COPY app /app # No USER directive — runs as root! CMD ["/app/server"]
FROM gcr.io/distroless/static:nonroot COPY --chown=65534:65534 app /app USER 65534:65534 EXPOSE 8080 ENTRYPOINT ["/app/server"]
클라우드 네이티브 애플리케이션은 기존 HTTP 요청뿐만 아니라 클라우드 이벤트(SQS, Pub/Sub, EventBridge), 서버리스 트리거, 서비스 간 통신으로부터도 입력을 받습니다. 이러한 벡터 중 하나에서 인젝션 결함이 발생하면 명령 실행, 데이터 유출 또는 권한 상승으로 이어질 수 있습니다.
클라우드 이벤트에 의해 트리거되는 서버리스 함수는 유효성 검사 없이 신뢰할 수 없는 데이터를 처리하여 OS 명령 인젝션, NoSQL 인젝션 또는 이벤트 기반 SSRF를 유발할 수 있습니다. 공격자는 메시지 큐나 이벤트 버스를 오염시켜 다운스트림 서비스를 손상시킬 수 있습니다.
# Lambda function processing S3 event without sanitizing filename import os def handler(event, context): bucket = event['Records'][0]['s3']['bucket']['name'] key = event['Records'][0]['s3']['object']['key'] # Command injection via crafted filename! os.system(f"aws s3 cp s3://{bucket}/{key} /tmp/{key}")
import boto3, re from urllib.parse import unquote_plus def handler(event, context): s3 = boto3.client('s3') bucket = event['Records'][0]['s3']['bucket']['name'] key = unquote_plus(event['Records'][0]['s3']['object']['key']) # Validate key against allowlist pattern if not re.match(r'^[\w\-./]+$', key): raise ValueError(f"Invalid S3 key: {key}") # Use SDK instead of shell commands s3.download_file(bucket, key, f'/tmp/{key.split("/")[-1]}')
클라우드 네이티브 환경에는 클라우드 IAM, Kubernetes RBAC, 서비스 메시 mTLS, 애플리케이션 수준 인증 등 여러 계층의 ID가 포함됩니다. 어느 계층에서든 잘못 구성되거나 지나치게 허용적인 정책을 사용하면 측면 이동, 권한 에스컬레이션 또는 민감한 리소스에 대한 무단 액세스가 허용될 수 있습니다.
파드에 과도하게 허용된 IAM 역할은 워크로드에 전체 클라우드 계정에 대한 액세스 권한을 부여할 수 있습니다. 서비스 간 인증이 누락되면 손상된 파드가 다른 서비스를 가장할 수 있습니다.
# Overly permissive ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: default-admin subjects: - kind: ServiceAccount name: default # Default SA — shared by all pods! namespace: default roleRef: kind: ClusterRole name: cluster-admin # Full cluster access! apiGroup: rbac.authorization.k8s.io
# Dedicated ServiceAccount with minimal Role apiVersion: v1 kind: ServiceAccount metadata: name: order-service namespace: production annotations: eks.amazonaws.com/role-arn: arn:aws:iam::123456:role/order-svc --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: order-service-role namespace: production rules: - apiGroups: [""] resources: ["configmaps"] verbs: ["get"]
CI/CD 파이프라인은 프로덕션 환경에 대한 쓰기 권한이 있기 때문에 가치가 높은 공격 대상입니다. 빌드 파이프라인이 손상되면 공급망 공격, 악성 코드 삽입, 백도어 이미지 배포가 가능해집니다. 안전하지 않은 파이프라인 구성, 포이즌된 기본 이미지, 서명되지 않은 아티팩트가 모두 이러한 위험의 원인이 됩니다.
손상된 CI/CD 파이프라인은 모든 환경에 악성 코드를 배포하고, 파이프라인 변수에 저장된 기밀을 훔치거나 컨테이너 이미지를 변조할 수 있습니다. 솔라윈즈 스타일의 공격은 공급망 침해가 얼마나 치명적인 영향을 미치는지 보여줍니다.
# Insecure CI pipeline — unpinned actions, no image signing name: Deploy on: push jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@main # Unpinned — could be compromised! - run: | docker build -t myapp:latest . docker push myregistry/myapp:latest # No signing! kubectl apply -f deploy.yaml # No admission control!
name: Secure Deploy on: push permissions: id-token: write jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # Pinned SHA - run: | docker build -t myregistry/myapp:${{ github.sha }} . cosign sign myregistry/myapp:${{ github.sha }} # Sign image - run: trivy image myregistry/myapp:${{ github.sha }} --exit-code 1 - run: kubectl apply -f deploy.yaml # Admission controller verifies signatures
API 키, 데이터베이스 자격 증명, TLS 인증서와 같은 시크릿은 소스 코드에 하드코딩되거나, 일반 텍스트 컨피그맵에 저장되거나, 컨테이너 이미지에 임베드되는 경우가 많습니다. 쿠버네티스 시크릿은 기본적으로 암호화되지 않고 base64로만 인코딩되어 최소한의 보호만 제공합니다.
노출된 비밀은 공격자가 데이터베이스, 클라우드 계정 및 타사 서비스에 직접 액세스할 수 있게 해줍니다. Git 기록, 컨테이너 레이어 또는 환경 변수의 비밀은 쉽게 발견되고 악용될 수 있습니다.
# Secrets in plaintext environment variables apiVersion: v1 kind: Pod metadata: name: my-app spec: containers: - name: app env: - name: DB_PASSWORD value: "SuperSecret123!" # Plaintext in manifest! - name: AWS_SECRET_KEY value: "AKIA..." # Cloud credentials in YAML!
# Use External Secrets Operator with a vault backend apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: my-app-secrets spec: refreshInterval: 1h secretStoreRef: name: vault-backend kind: ClusterSecretStore target: name: my-app-secrets data: - secretKey: db-password remoteRef: key: secret/data/myapp property: db-password
기본적으로 쿠버네티스는 모든 파드가 제한 없이 서로 통신할 수 있도록 허용합니다. 누락되거나 지나치게 허용적인 네트워크 정책, 보안 그룹 및 방화벽 규칙은 클러스터 내에서 그리고 클라우드 서비스 간에 횡방향 이동을 가능하게 합니다.
네트워크 세분화가 없으면 손상된 파드는 클러스터의 다른 서비스에 도달하거나 데이터베이스에 직접 액세스하거나 외부 엔드포인트로 데이터를 유출할 수 있습니다. 플랫 네트워크는 모든 침해의 폭발 반경을 증폭시킵니다.
# No NetworkPolicy — all pods can talk to everything apiVersion: v1 kind: Namespace metadata: name: production # No NetworkPolicy resources defined # All ingress and egress traffic is allowed by default
# Default-deny all traffic, then allow only what's needed apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: default-deny-all namespace: production spec: podSelector: {} policyTypes: ["Ingress", "Egress"] --- apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-frontend-to-api namespace: production spec: podSelector: matchLabels: app: api-server ingress: - from: - podSelector: matchLabels: app: frontend ports: - port: 8080
클라우드 네이티브 애플리케이션은 오픈 소스 기본 이미지, 라이브러리 및 Kubernetes 운영자에 크게 의존합니다. 오래된 구성 요소나 패치되지 않은 구성 요소를 실행하면 애플리케이션이 잘 문서화된 익스플로잇에 노출됩니다. 컨테이너 이미지에는 수백 개의 패키지가 포함되어 있는 경우가 많으며, 각 패키지는 잠재적인 취약점이 있습니다.
기본 이미지의 알려진 취약점(예: Log4Shell, OpenSSL 버그)은 공개적으로 사용 가능한 도구를 사용하여 익스플로잇할 수 있습니다. 공격자는 취약한 버전을 실행하는 컨테이너를 적극적으로 검색합니다. 패치되지 않은 라이브러리 하나만으로도 전체 워크로드가 손상될 수 있습니다.
# Using outdated base image with known CVEs FROM node:14 # EOL version with known vulns COPY package.json . RUN npm install # No audit, no lockfile verification COPY . . CMD ["node", "server.js"]
# Use current, slim base image with vulnerability scanning FROM node:22-slim AS build WORKDIR /app COPY package.json package-lock.json ./ RUN npm ci --only=production # Reproducible install from lockfile RUN npm audit --audit-level=high # Fail on high+ vulns FROM gcr.io/distroless/nodejs22-debian12 COPY --from=build /app /app CMD ["/app/server.js"]
클라우드 네이티브 환경에서는 리소스를 쉽게 스핀업할 수 있지만 추적하기는 어렵습니다. 고아가 된 컨테이너, 잊혀진 네임스페이스, 오래된 클라우드 리소스, 섀도 IT 배포는 관리되지 않는 공격 표면을 만듭니다. 적절한 자산 인벤토리가 없으면 보안팀은 존재 여부도 모르는 자산을 보호할 수 없습니다.
잊혀지거나 관리되지 않는 리소스는 오래된 소프트웨어를 실행하고 보안 모니터링이 부족하며 오래된 자격 증명이 있는 경우가 많습니다. 공격자들은 모니터링이나 패치 가능성이 낮기 때문에 이러한 방치된 자산을 공격의 진입 지점으로 삼습니다.
# Resources created without tagging or lifecycle management resource "aws_instance" "test_server" { ami = "ami-0abcdef1234567890" instance_type = "t3.medium" # No tags — who owns this? What's it for? # No lifecycle policy — runs forever } resource "aws_s3_bucket" "temp_data" { bucket = "temp-data-2024" # No expiration, no access logging }
resource "aws_instance" "test_server" { ami = "ami-0abcdef1234567890" instance_type = "t3.medium" tags = { Name = "test-server" Owner = "platform-team" Environment = "staging" ManagedBy = "terraform" ExpiresAt = "2026-04-30" } } resource "aws_s3_bucket" "temp_data" { bucket = "temp-data-2024" tags = { Owner = "data-team" ManagedBy = "terraform" } lifecycle_rule { enabled = true expiration { days = 90 } } }
적절한 리소스 할당량과 제한이 없으면 하나의 잘못된 동작 또는 손상된 워크로드가 사용 가능한 모든 CPU, 메모리 또는 스토리지를 소비하여 다른 애플리케이션에 대한 서비스 거부를 일으킬 수 있습니다. 크립토재킹 공격은 리소스 제한이 없는 환경에서 특히 흔합니다.
공격자는 모든 클러스터 리소스를 소비하는 크립토마이닝 컨테이너 또는 리소스 집약적인 워크로드를 배포할 수 있습니다. 한 포드에서 포크 폭탄이나 메모리 누수가 발생하면 전체 노드가 다운되어 함께 배치된 모든 워크로드에 영향을 미칠 수 있습니다.
# Pod with no resource limits apiVersion: v1 kind: Pod metadata: name: my-app spec: containers: - name: app image: myapp:latest # No resources block — can consume unlimited CPU/memory!
apiVersion: v1 kind: Pod metadata: name: my-app spec: containers: - name: app image: myapp:1.2.3 resources: requests: cpu: "100m" memory: "128Mi" limits: cpu: "500m" memory: "512Mi" --- # Namespace-level quota apiVersion: v1 kind: ResourceQuota metadata: name: compute-quota namespace: production spec: hard: requests.cpu: "10" requests.memory: "20Gi" limits.cpu: "20" limits.memory: "40Gi"
클라우드 네이티브 환경은 애플리케이션, 컨테이너 런타임, 오케스트레이터, 서비스 메시, 클라우드 플랫폼 등 여러 계층에 걸쳐 로그를 생성합니다. 중앙 집중식 로깅, 이러한 계층 간의 상관관계, 런타임 위협 탐지가 없으면 보안 인시던트가 탐지되지 않거나 너무 늦게 발견됩니다.
임시 컨테이너는 종료되면 로그가 손실되어 포렌식 증거가 파괴됩니다. Kubernetes 감사 로그와 런타임 모니터링이 없으면 공격자는 백도어를 생성하거나 권한을 에스컬레이션하거나 경고를 트리거하지 않고도 데이터를 유출할 수 있습니다.
# No audit policy, no log forwarding apiVersion: v1 kind: Pod metadata: name: my-app spec: containers: - name: app image: myapp:latest # Logs go to stdout only — lost when pod restarts # No audit logging configured on the cluster # No runtime security monitoring
# Kubernetes audit policy for security events apiVersion: audit.k8s.io/v1 kind: Policy rules: - level: RequestResponse resources: - group: "" resources: ["secrets", "configmaps"] - level: Metadata resources: - group: "rbac.authorization.k8s.io" resources: ["clusterroles", "clusterrolebindings"] - level: Metadata verbs: ["create", "delete", "patch"] # Deploy Falco for runtime threat detection # Forward logs to SIEM via Fluent Bit / Fluentd
| ID | 취약성 | 심각도 | 주요 완화 |
|---|---|---|---|
| CNAS-1 | 안전하지 않은 클라우드/컨테이너/오케스트레이션 구성 | Critical | 배포되지 않은 이미지, 포드 보안 표준, IaC 스캔 |
| CNAS-2 | 주입 결함(클라우드 이벤트) | Critical | 입력 유효성 검사, SDK 오버 셸, 송신 필터링 |
| CNAS-3 | 부적절한 인증 및 권한 부여 | Critical | 최소 권한 RBAC, IRSA, mTLS |
| CNAS-4 | CI/CD 파이프라인 및 공급망 결함 | High | 고정 SHA, 이미지 서명, SLSA 출처 증명 |
| CNAS-5 | 안전하지 않은 비밀 저장소 | Critical | 볼트/시크릿 관리자, KMS 암호화, 비밀 스캔 |
| CNAS-6 | 과도하게 허용되는 네트워크 정책 | High | 기본 거부, 송신 제한, 캘리코/실리움 |
| CNAS-7 | 알려진 취약점이 있는 구성 요소 | High | 이미지 스캔, 최소한의 기본 이미지, SBOM |
| CNAS-8 | 부적절한 자산 관리 | Medium | 리소스 태깅, 자동 정리, IaC |
| CNAS-9 | 부적절한 컴퓨팅 리소스 할당량 | Medium | 리소스 제한, 리소스 할당량, 사용량 모니터링 |
| CNAS-10 | 비효율적인 로깅 및 모니터링 | High | 감사 로그, Falco/Sysdig, 중앙 집중식 SIEM |