Skip to content

필사 모드: 보안 취약점 조치 플레이북: OS 패키지 · 컨테이너 이미지 · 런타임 하드닝

한국어
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.
원문 렌더가 준비되기 전까지 텍스트 가이드로 표시합니다.

들어가며

보안 스캐너가 CVE 목록을 쏟아내면 어디서부터 손대야 할지 막막해진다. 중요한 것은 **모든 취약점을 즉시 고치는 것이 아니라, 리스크를 기준으로 우선순위를 매기고, 체계적으로 조치하고, 재발을 방지하는 프로세스**를 갖추는 것이다.

이 글에서는 **OS 패키지 취약점 패치, 컨테이너 이미지 보안, 런타임 하드닝**을 아우르는 실전 플레이북을 제시한다.

1. 취약점 대응 프로세스 개요

┌─────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐

│ 발견 │ → │ 분류 │ → │ 조치 │ → │ 검증 │ → │ 보고 │

│ Scanning │ │ Triage │ │ Remediate│ │ Verify │ │ Report │

└─────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘

대응 SLA (권장)

| 심각도 | CVSS 점수 | 조치 기한 | 예시 |

| ------------ | --------- | ------------------------ | -------------------- |

| **Critical** | 9.0~10.0 | 24~72시간 | RCE, 인증 우회 |

| **High** | 7.0~8.9 | 7일 | 권한 상승, 정보 유출 |

| **Medium** | 4.0~6.9 | 30일 | XSS, 서비스 거부 |

| **Low** | 0.1~3.9 | 90일 또는 다음 정기 패치 | 정보 노출 (제한적) |

> **핵심 원칙**: CVSS 점수만으로 판단하지 말고, **Exploit 가능 여부(EPSS)**, **인터넷 노출 여부**, **영향받는 자산의 중요도**를 종합 판단한다.

2. OS 패키지 취약점 관리

2.1 취약점 스캔

RHEL / Rocky - 보안 업데이트 확인

dnf updateinfo list security

dnf updateinfo list --sec-severity=Critical

dnf updateinfo info RHSA-2026:1234

Ubuntu - 보안 업데이트 확인

apt update

apt list --upgradable 2>/dev/null | grep -i security

설치된 패키지의 CVE 확인 (Trivy)

trivy rootfs --severity CRITICAL,HIGH /

OpenSCAP 스캔 (컴플라이언스)

oscap xccdf eval \

--profile xccdf_org.ssgproject.content_profile_cis \

--results results.xml \

--report report.html \

/usr/share/xml/scap/ssg/content/ssg-rhel9-ds.xml

2.2 패치 적용 절차

#!/usr/bin/env bash

patch-os.sh - OS 보안 패치 적용 스크립트

set -euo pipefail

LOG_FILE="/var/log/security-patch-$(date +%Y%m%d).log"

SNAPSHOT_NAME="pre-patch-$(date +%Y%m%d-%H%M%S)"

log() { printf '[%s] %s\n' "$(date +%T)" "$1" | tee -a "$LOG_FILE"; }

1단계: 스냅샷/백업

log "=== 패치 시작 ==="

log "스냅샷 생성: $SNAPSHOT_NAME"

LVM 스냅샷 (해당 시)

lvcreate -L 10G -s -n "$SNAPSHOT_NAME" /dev/vg0/root

2단계: 현재 상태 기록

rpm -qa --qf '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' | sort > /tmp/packages-before.txt

3단계: 보안 업데이트만 적용

log "보안 업데이트 적용 중..."

if command -v dnf &>/dev/null; then

dnf update --security -y 2>&1 | tee -a "$LOG_FILE"

elif command -v apt-get &>/dev/null; then

apt-get update

apt-get upgrade -y -o Dpkg::Options::="--force-confold" 2>&1 | tee -a "$LOG_FILE"

fi

4단계: 변경된 패키지 목록

rpm -qa --qf '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' | sort > /tmp/packages-after.txt

diff /tmp/packages-before.txt /tmp/packages-after.txt > /tmp/packages-diff.txt || true

log "변경된 패키지:"

cat /tmp/packages-diff.txt | tee -a "$LOG_FILE"

5단계: 서비스 재시작 필요 여부 확인

if command -v needs-restarting &>/dev/null; then

log "재시작 필요 서비스:"

needs-restarting -s 2>&1 | tee -a "$LOG_FILE"

if needs-restarting -r 2>&1 | grep -q "Reboot is required"; then

log "WARNING: 커널 업데이트로 리부팅 필요"

fi

fi

log "=== 패치 완료 ==="

2.3 자동 보안 업데이트 설정

RHEL / Rocky

dnf-automatic 설치·설정

dnf install -y dnf-automatic

/etc/dnf/automatic.conf

[commands]

apply_updates = yes

upgrade_type = security # 보안 업데이트만

systemctl enable --now dnf-automatic-install.timer

Ubuntu

unattended-upgrades 설정

apt install -y unattended-upgrades

dpkg-reconfigure -plow unattended-upgrades

/etc/apt/apt.conf.d/50unattended-upgrades

Unattended-Upgrade::Allowed-Origins {

"${distro_id}:${distro_codename}-security";

};

Unattended-Upgrade::Automatic-Reboot "false";

Unattended-Upgrade::Mail "admin@example.com";

2.4 패치 관리 체크리스트

- [ ] 보안 업데이트 알림 채널 구독 (RHSA, USN, CVE 메일링 리스트)

- [ ] 주간 취약점 스캔 자동화

- [ ] 스테이징 → 프로덕션 패치 파이프라인 구축

- [ ] 패치 적용 전 스냅샷/백업 필수

- [ ] 패치 후 서비스 헬스체크 자동화

- [ ] 커널 업데이트 시 재부팅 일정 수립

- [ ] 패치 이력·감사 로그 보존 (최소 1년)

3. 컨테이너 이미지 보안

3.1 이미지 스캔 도구 비교

| 도구 | 라이선스 | 특징 | CI/CD 통합 |

| -------------------- | ---------------- | ------------------------------- | ------------------------- |

| **Trivy** | OSS (Apache-2.0) | OS + 언어 패키지 + IaC + Secret | GitHub Actions, GitLab CI |

| **Grype** | OSS (Apache-2.0) | SBOM 기반 스캔 | CLI 중심 |

| **Snyk Container** | 상용 (무료 플랜) | 개발자 친화적 Fix PR | 대부분 CI |

| **Prisma Cloud** | 상용 | 전체 CNAPP | 엔터프라이즈 CI |

| **AWS ECR Scanning** | AWS 포함 | Inspector 기반 | AWS 네이티브 |

3.2 Trivy 실전 사용

이미지 스캔 (Critical + High만)

trivy image --severity CRITICAL,HIGH myapp:latest

SBOM 생성

trivy image --format spdx-json -o sbom.json myapp:latest

취약점이 있으면 빌드 실패 (CI용)

trivy image --exit-code 1 --severity CRITICAL myapp:latest

.trivyignore - 허용된 취약점 (예외 처리)

CVE-2024-XXXX # 해당 코드 경로 미사용, 2026-04-01까지 예외

3.3 안전한 Dockerfile 작성

1. 최소 베이스 이미지 사용

FROM cgr.dev/chainguard/python:latest-dev AS builder

또는 distroless, Alpine, UBI-micro

2. 빌드 의존성과 런타임 분리 (멀티스테이지)

WORKDIR /app

COPY requirements.txt .

RUN pip install --no-cache-dir --prefix=/install -r requirements.txt

COPY . .

FROM cgr.dev/chainguard/python:latest

WORKDIR /app

COPY --from=builder /install /usr/local

COPY --from=builder /app .

3. non-root 사용자 (Chainguard은 기본 non-root)

일반 이미지의 경우:

RUN addgroup -S app && adduser -S app -G app

USER app

4. 불필요한 패키지 제거, 캐시 정리

(멀티스테이지로 해결)

5. 건강 검사

HEALTHCHECK --interval=30s --timeout=5s --retries=3 \

CMD ["python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8000/health')"]

ENTRYPOINT ["python", "-m", "uvicorn", "main:app", "--host", "0.0.0.0"]

3.4 베이스 이미지 선택 가이드

| 이미지 유형 | 크기 | 취약점 수 | 패키지 매니저 | 쉘 | 추천 용도 |

| -------------- | ----- | --------- | ------------- | ----------- | --------------- |

| `ubuntu:24.04` | ~78MB | 중간 | apt | bash | 범용 |

| `alpine:3.20` | ~7MB | 낮음 | apk | ash | 경량 서비스 |

| `distroless` | ~20MB | 매우 낮음 | 없음 | 없음 | 프로덕션 런타임 |

| `chainguard` | ~15MB | 거의 0 | apk (dev만) | 없음(dev만) | 보안 중시 |

| `ubi-micro` | ~35MB | 낮음 | 없음 | 없음 | RHEL 호환 필요 |

| `scratch` | 0MB | 0 | 없음 | 없음 | Go 바이너리 |

3.5 CI/CD 파이프라인 통합

GitHub Actions 예시

name: Container Security

on:

push:

branches: [main]

pull_request:

jobs:

scan:

runs-on: ubuntu-latest

steps:

- uses: actions/checkout@v4

- name: Build image

run: docker build -t myapp:${{ github.sha }} .

- name: Trivy vulnerability scan

uses: aquasecurity/trivy-action@master

with:

image-ref: myapp:${{ github.sha }}

severity: CRITICAL,HIGH

exit-code: 1

format: sarif

output: trivy-results.sarif

- name: Upload scan results

uses: github/codeql-action/upload-sarif@v3

if: always()

with:

sarif_file: trivy-results.sarif

- name: Generate SBOM

uses: aquasecurity/trivy-action@master

with:

image-ref: myapp:${{ github.sha }}

format: spdx-json

output: sbom.spdx.json

- name: Upload SBOM

uses: actions/upload-artifact@v4

with:

name: sbom

path: sbom.spdx.json

4. 런타임 하드닝

4.1 컨테이너 런타임 보안

Docker 하드닝

/etc/docker/daemon.json

{

"userns-remap": "default",

"no-new-privileges": true,

"log-driver": "json-file",

"log-opts": {

"max-size": "10m",

"max-file": "3"

},

"storage-driver": "overlay2",

"live-restore": true,

"icc": false,

"default-ulimits": {

"nofile": { "Name": "nofile", "Hard": 65535, "Soft": 65535 }

}

}

컨테이너 실행 시 보안 옵션

docker run -d \

--name myapp \

--read-only \

--tmpfs /tmp:rw,noexec,nosuid,size=100m \

--cap-drop ALL \

--cap-add NET_BIND_SERVICE \

--security-opt no-new-privileges:true \

--security-opt seccomp=default.json \

--pids-limit 100 \

--memory 512m \

--cpus 1.0 \

--user 1000:1000 \

myapp:latest

Kubernetes Pod Security

Pod Security Standards - Restricted 프로파일

apiVersion: v1

kind: Pod

metadata:

name: secure-app

spec:

securityContext:

runAsNonRoot: true

runAsUser: 1000

runAsGroup: 1000

fsGroup: 1000

seccompProfile:

type: RuntimeDefault

containers:

- name: app

image: myapp:latest

securityContext:

allowPrivilegeEscalation: false

readOnlyRootFilesystem: true

capabilities:

drop: ['ALL']

resources:

limits:

memory: 512Mi

cpu: '1'

requests:

memory: 256Mi

cpu: '0.5'

volumeMounts:

- name: tmp

mountPath: /tmp

volumes:

- name: tmp

emptyDir:

sizeLimit: 100Mi

4.2 Kubernetes 클러스터 하드닝 체크리스트

| 영역 | 항목 | 명령/설정 |

| ------------ | ---------------------------- | -------------------------------------------- |

| **인증** | 익명 접근 차단 | `--anonymous-auth=false` |

| **인가** | RBAC 활성화 | `--authorization-mode=RBAC` |

| **API** | NodeRestriction 어드미션 | `--enable-admission-plugins=NodeRestriction` |

| **Etcd** | 암호화 설정 | `--encryption-provider-config` |

| **네트워크** | NetworkPolicy 적용 | Calico/Cilium 네트워크 정책 |

| **Pod** | PSA (Pod Security Admission) | 네임스페이스에 `enforce: restricted` |

| **시크릿** | 외부 시크릿 관리자 | Vault, AWS Secrets Manager |

| **감사** | Audit 로깅 | `--audit-log-path`, `--audit-policy-file` |

| **이미지** | 서명 검증 | Cosign + Admission Webhook |

| **런타임** | Seccomp/AppArmor 프로파일 | Pod securityContext |

4.3 네트워크 정책 예시

기본 거부 정책 (deny-all)

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-app-traffic

namespace: production

spec:

podSelector:

matchLabels:

app: myapp

policyTypes:

- Ingress

- Egress

ingress:

- from:

- podSelector:

matchLabels:

app: nginx-ingress

ports:

- port: 8080

protocol: TCP

egress:

- to:

- podSelector:

matchLabels:

app: postgres

ports:

- port: 5432

protocol: TCP

- to: # DNS 허용

- namespaceSelector: {}

podSelector:

matchLabels:

k8s-app: kube-dns

ports:

- port: 53

protocol: UDP

- port: 53

protocol: TCP

5. 취약점 대응 시나리오별 플레이북

시나리오 1: Critical CVE 긴급 패치

1. [즉시] CVE 공지 확인 → 영향받는 패키지·버전 식별

2. [1시간] 자산 인벤토리에서 영향 범위 파악

3. [2시간] 패치 가용 여부 확인

├── 패치 있음 → 스테이징 적용 → 테스트 → 프로덕션 롤링

└── 패치 없음 → Workaround 적용 (WAF 룰, 설정 변경, 서비스 격리)

4. [24시간] 프로덕션 패치 완료

5. [48시간] 스캔으로 조치 검증 → 보고서 작성

시나리오 2: 컨테이너 이미지 취약점

1. 이미지 스캔 결과 확인 (Trivy/Snyk)

2. 취약점 분류:

├── OS 패키지 → 베이스 이미지 업데이트

├── 언어 라이브러리 → dependency 업데이트

└── 설정 문제 → Dockerfile 수정

3. 이미지 재빌드 + 스캔 재실행

4. 스테이징 배포 → E2E 테스트

5. 프로덕션 롤링 업데이트

6. 이전 이미지 태그 비활성화

시나리오 3: 런타임 침해 탐지 대응

1. [즉시] 알림 확인 (Falco, 감사 로그)

2. [즉시] 해당 Pod/컨테이너 격리 (NetworkPolicy deny-all)

3. [1시간] 포렌식 데이터 수집:

- 컨테이너 프로세스 목록, 네트워크 연결

- 감사 로그, 런타임 이벤트 로그

- 이미지 레이어 분석

4. [4시간] 침입 경로 파악 → 취약점 조치

5. [24시간] 클린 이미지로 재배포

6. [1주] 사후 분석 보고서 + 재발 방지 대책

6. 보안 스캔 자동화 아키텍처

┌─────────────┐ ┌─────────────┐ ┌─────────────┐

│ 코드 푸시 │ → │ CI 파이프라인 │ → │ 이미지 빌드 │

└─────────────┘ └──────┬──────┘ └──────┬──────┘

│ │

┌──────▼──────┐ ┌──────▼──────┐

│ SAST 스캔 │ │ 이미지 스캔 │

│ (Semgrep) │ │ (Trivy) │

└──────┬──────┘ └──────┬──────┘

│ │

┌──────▼───────────────────▼──────┐

│ 결과 집계 + 판정 │

│ (Critical → 빌드 실패) │

│ (High → 경고 + Jira 생성) │

└──────────────┬──────────────────┘

┌──────────────▼──────────────────┐

│ 레지스트리 푸시 (통과 시에만) │

└──────────────┬──────────────────┘

┌──────────────▼──────────────────┐

│ 정기 스캔 (주간, 레지스트리 전체) │

└─────────────────────────────────┘

7. 컴플라이언스 매핑

| 프레임워크 | 관련 요구사항 | 이 플레이북의 대응 |

| ----------------- | ---------------------------------- | ------------------ |

| **CIS Benchmark** | OS·Docker·K8s 벤치마크 | 섹션 2, 4 |

| **NIST 800-53** | SI-2 (Flaw Remediation) | 섹션 2 (패치 관리) |

| **PCI DSS 4.0** | 6.3 (취약점 식별·조치) | 전체 프로세스 |

| **SOC 2** | CC7.1 (모니터링), CC8.1 (변경관리) | 섹션 5, 6 |

| **ISMS-P** | 2.10 (시스템·서비스 보안관리) | 전체 |

8. 도구 체인 추천

필수 도구

| 용도 | OSS | 상용 |

| --------------- | ----------------------- | -------------------- |

| 이미지 스캔 | Trivy, Grype | Snyk, Prisma Cloud |

| OS 컴플라이언스 | OpenSCAP, Lynis | Qualys, Tenable |

| 런타임 보안 | Falco | Sysdig Secure |

| SBOM 생성 | Syft, Trivy | Anchore |

| 시크릿 스캔 | Gitleaks, TruffleHog | GitGuardian |

| SAST | Semgrep, CodeQL | SonarQube, Checkmarx |

| 이미지 서명 | Cosign (Sigstore) | Docker Content Trust |

| 정책 엔진 | OPA/Gatekeeper, Kyverno | Styra DAS |

최소 구성 추천

코드 단계: Gitleaks (시크릿) + Semgrep (SAST)

빌드 단계: Trivy (이미지 스캔) + Syft (SBOM)

배포 단계: Cosign (이미지 서명) + Kyverno (정책)

런타임: Falco (이상 탐지) + 감사 로그

9. 보고서 템플릿

취약점 조치 보고서

보안 취약점 조치 보고서

개요

- 보고일: YYYY-MM-DD

- 작성자: 보안 운영팀

- 대상 기간: YYYY-MM-DD ~ YYYY-MM-DD

요약

| 심각도 | 발견 | 조치 완료 | 예외 처리 | 미조치 |

| -------- | ---- | --------- | --------- | ------ |

| Critical | 3 | 3 | 0 | 0 |

| High | 12 | 10 | 2 | 0 |

| Medium | 45 | 30 | 5 | 10 |

Critical 취약점 상세

CVE-YYYY-XXXXX

- 영향: [설명]

- 영향 자산: [서버/이미지 목록]

- 조치: [패치 버전/설정 변경]

- 조치일: YYYY-MM-DD

- 검증: [스캔 결과 첨부]

예외 처리 목록

| CVE | 사유 | 보완 조치 | 만료일 |

| -------------- | --------------------- | ----------- | ---------- |

| CVE-YYYY-XXXXX | 해당 코드 경로 미사용 | WAF 룰 추가 | YYYY-MM-DD |

개선 권고사항

1. [구체적 개선 사항]

2. [구체적 개선 사항]

10. 실전 점검 체크리스트

OS 보안

- [ ] 불필요한 서비스 비활성화 (`systemctl list-unit-files --state=enabled`)

- [ ] SSH 키 기반 인증만 허용, root 로그인 차단

- [ ] 자동 보안 업데이트 설정

- [ ] 방화벽 기본 거부(deny) 정책

- [ ] 감사 로그(auditd) 활성화

- [ ] AIDE/OSSEC 파일 무결성 모니터링

컨테이너 보안

- [ ] 최소 베이스 이미지 사용 (distroless/chainguard)

- [ ] 멀티스테이지 빌드로 빌드 도구 제거

- [ ] non-root 사용자로 실행

- [ ] 읽기 전용 파일시스템

- [ ] 리소스 제한 (CPU, 메모리, PID)

- [ ] 이미지 서명 + 검증

Kubernetes 보안

- [ ] PSA(Pod Security Admission) restricted 모드

- [ ] NetworkPolicy 기본 deny-all

- [ ] RBAC 최소 권한 원칙

- [ ] Etcd 암호화

- [ ] 감사 로깅 활성화

- [ ] 시크릿 외부 관리 (Vault 등)

마무리

보안은 한 번의 조치가 아니라 **지속적인 프로세스**다. 이 플레이북의 핵심을 세 줄로 요약한다.

1. **자동화**: 스캔·패치·검증을 CI/CD에 내장하여 수동 누락을 방지한다.

2. **계층 방어**: OS·이미지·런타임·네트워크를 모두 다루는 심층 방어 전략을 수립한다.

3. **대응 체계**: 발견→분류→조치→검증→보고의 사이클을 반복하며, SLA를 지킨다.

완벽한 보안은 불가능하지만, 체계적인 운영으로 **리스크를 관리 가능한 수준으로 낮출 수 있다**.

현재 단락 (1/357)

보안 스캐너가 CVE 목록을 쏟아내면 어디서부터 손대야 할지 막막해진다. 중요한 것은 **모든 취약점을 즉시 고치는 것이 아니라, 리스크를 기준으로 우선순위를 매기고, 체계적으로 ...

작성 글자: 0원문 글자: 10,793작성 단락: 0/357