Skip to content

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

✨ Learn with Quiz
|

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

들어가며

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

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


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

┌─────────┐    ┌──────────┐    ┌──────────┐    ┌──────────┐    ┌──────────┐
│  발견    │ → │  분류    │ → │  조치    │ → │  검증    │ → │  보고    │
Scanning │    │ Triage   │    │ Remediate│Verify   │    │ Report└─────────┘    └──────────┘    └──────────┘    └──────────┘    └──────────┘

대응 SLA (권장)

심각도CVSS 점수조치 기한예시
Critical9.0~10.024~72시간RCE, 인증 우회
High7.0~8.97일권한 상승, 정보 유출
Medium4.0~6.930일XSS, 서비스 거부
Low0.1~3.990일 또는 다음 정기 패치정보 노출 (제한적)

핵심 원칙: 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 통합
TrivyOSS (Apache-2.0)OS + 언어 패키지 + IaC + SecretGitHub Actions, GitLab CI
GrypeOSS (Apache-2.0)SBOM 기반 스캔CLI 중심
Snyk Container상용 (무료 플랜)개발자 친화적 Fix PR대부분 CI
Prisma Cloud상용전체 CNAPP엔터프라이즈 CI
AWS ECR ScanningAWS 포함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중간aptbash범용
alpine:3.20~7MB낮음apkash경량 서비스
distroless~20MB매우 낮음없음없음프로덕션 런타임
chainguard~15MB거의 0apk (dev만)없음(dev만)보안 중시
ubi-micro~35MB낮음없음없음RHEL 호환 필요
scratch0MB0없음없음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
APINodeRestriction 어드미션--enable-admission-plugins=NodeRestriction
Etcd암호화 설정--encryption-provider-config
네트워크NetworkPolicy 적용Calico/Cilium 네트워크 정책
PodPSA (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 BenchmarkOS·Docker·K8s 벤치마크섹션 2, 4
NIST 800-53SI-2 (Flaw Remediation)섹션 2 (패치 관리)
PCI DSS 4.06.3 (취약점 식별·조치)전체 프로세스
SOC 2CC7.1 (모니터링), CC8.1 (변경관리)섹션 5, 6
ISMS-P2.10 (시스템·서비스 보안관리)전체

8. 도구 체인 추천

필수 도구

용도OSS상용
이미지 스캔Trivy, GrypeSnyk, Prisma Cloud
OS 컴플라이언스OpenSCAP, LynisQualys, Tenable
런타임 보안FalcoSysdig Secure
SBOM 생성Syft, TrivyAnchore
시크릿 스캔Gitleaks, TruffleHogGitGuardian
SASTSemgrep, CodeQLSonarQube, Checkmarx
이미지 서명Cosign (Sigstore)Docker Content Trust
정책 엔진OPA/Gatekeeper, KyvernoStyra 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를 지킨다.

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

Security vulnerability action playbook: OS package, container image, runtime hardening

Entering

When a security scanner pours out a list of CVEs, it becomes difficult to know where to start. The important thing is not to immediately fix all vulnerabilities, but to have a process to prioritize based on risk, take systematic action, and prevent recurrence.

In this article, we present a practical playbook covering OS package vulnerability patching, container image security, and runtime hardening.


1. Vulnerability response process overview


┌─────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ 발견 │ → │ 분류 │ → │ 조치 │ → │ 검증 │ → │ 보고 │
Scanning │ │ Triage │ │ Remediate│Verify │ │ Report└─────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘

SeverityCVSS scoreAction DeadlineExample
Critical9.0~10.024~72 hoursRCE, authentication bypass
High7.0~8.97 daysEscalation of privilege, information leakage
Medium4.0~6.930 daysXSS, Denial of Service
Low0.1~3.990 days or next regular patchInformation disclosure (limited)

Core Principle: Do not judge only the CVSS score, but comprehensively judge Exploit Possibility (EPSS), Internet Exposure, and Importance of Affected Assets.


2. OS package vulnerability management

2.1 Vulnerability scan

# 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 Patch application procedure

#!/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 Automatic security update settings

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 Patch Management Checklist

  • Subscribe to security update notification channel (RHSA, USN, CVE mailing list)
  • Automated weekly vulnerability scanning
  • Staging → Building a production patch pipeline
  • Snapshot/backup required before patch application
  • Automation of service health check after patch
  • Establish reboot schedule when updating kernel
  • Preservation of patch history and audit log (at least 1 year)

3. Container image security

3.1 Comparison of image scanning tools

toolsLicenseFeaturesCI/CD integration
TrivyOSS (Apache-2.0)OS + language package + IaC + SecretGitHub Actions, GitLab CI
GrypeOSS (Apache-2.0)SBOM-based scanningCLI-centric
Snyk ContainerCommercial (Free Plan)Developer-friendly Fix PRMost CI
Prisma CloudcommercialAll CNAPPEnterprise CI
AWS ECR ScanningIncludes AWSInspector-basedAWS Native

3.2 Practical use of 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 Writing a secure 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 Base image selection guide

Image TypesizeNumber of vulnerabilitiespackage managershellRecommended use
ubuntu:24.04~78MBmiddleaptbashuniversal
alpine:3.20~7MBlowapkashlightweight service
distroless~20MBvery lowNoneNoneProduction Runtime
chainguard~15MBalmost 0apk (dev only)None (dev only)Focus on security
ubi-micro~35MBlowNoneNoneRequires RHEL Compatibility
scratch0MB0NoneNoneGo binary

3.5 CI/CD pipeline integration

# 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. Runtime hardening

4.1 Container runtime security

Docker hardening

# /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 }
  }
}

Security options when running containers

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 cluster hardening checklist

areaItemCommand/Settings
CertificationBlock anonymous access--anonymous-auth=false
Is itEnable RBAC--authorization-mode=RBAC
APINodeRestriction Admission--enable-admission-plugins=NodeRestriction
EtcdEncryption Settings--encryption-provider-config
NetworkApply NetworkPolicyCalico/Cilium Network Policy
PodPSA (Pod Security Admission)in the namespaceenforce: restricted
SecretExternal Secret ManagerVault, AWS Secrets Manager
ThanksAudit logging--audit-log-path, --audit-policy-file
ImageSignature VerificationCosign + Admission Webhook
RuntimeSeccomp/AppArmor ProfilePod securityContext

4.3 Network policy example

# 기본 거부 정책 (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. Playbook for each vulnerability response scenario

Scenario 1: Critical CVE Emergency Patch

1. [즉시] CVE 공지 확인 → 영향받는 패키지·버전 식별
2. [1시간] 자산 인벤토리에서 영향 범위 파악
3. [2시간] 패치 가용 여부 확인
   ├── 패치 있음 → 스테이징 적용 → 테스트 → 프로덕션 롤링
   └── 패치 없음 → Workaround 적용 (WAF, 설정 변경, 서비스 격리)
4. [24시간] 프로덕션 패치 완료
5. [48시간] 스캔으로 조치 검증 → 보고서 작성

Scenario 2: Container image vulnerability

1. 이미지 스캔 결과 확인 (Trivy/Snyk)
2. 취약점 분류:
   ├── OS 패키지 → 베이스 이미지 업데이트
   ├── 언어 라이브러리 → dependency 업데이트
   └── 설정 문제 → Dockerfile 수정
3. 이미지 재빌드 + 스캔 재실행
4. 스테이징 배포 → E2E 테스트
5. 프로덕션 롤링 업데이트
6. 이전 이미지 태그 비활성화

Scenario 3: Runtime breach detection response

1. [즉시] 알림 확인 (Falco, 감사 로그)
2. [즉시] 해당 Pod/컨테이너 격리 (NetworkPolicy deny-all)
3. [1시간] 포렌식 데이터 수집:
   - 컨테이너 프로세스 목록, 네트워크 연결
   - 감사 로그, 런타임 이벤트 로그
   - 이미지 레이어 분석
4. [4시간] 침입 경로 파악 → 취약점 조치
5. [24시간] 클린 이미지로 재배포
6. [1] 사후 분석 보고서 + 재발 방지 대책

6. Security scan automation architecture

┌─────────────┐    ┌─────────────┐    ┌─────────────┐
│  코드 푸시   │ → │  CI 파이프라인 │ → │  이미지 빌드  │
└─────────────┘    └──────┬──────┘    └──────┬──────┘
                          │                   │
                   ┌──────▼──────┐    ┌──────▼──────┐
SAST 스캔   │    │  이미지 스캔  │
                     (Semgrep)  (Trivy)                   └──────┬──────┘    └──────┬──────┘
                          │                   │
                   ┌──────▼───────────────────▼──────┐
                   │         결과 집계 + 판정          │
                      (Critical → 빌드 실패)                      (High → 경고 + Jira 생성)                   └──────────────┬──────────────────┘
                   ┌──────────────▼──────────────────┐
                   │  레지스트리 푸시 (통과 시에만)                   └──────────────┬──────────────────┘
                   ┌──────────────▼──────────────────┐
                   │  정기 스캔 (주간, 레지스트리 전체)                   └─────────────────────────────────┘

7. Compliance mapping

frameworkRelated RequirementsResponse from this playbook
CIS BenchmarkOS·Docker·K8s benchmarkSection 2, 4
NIST 800-53SI-2 (Flaw Remediation)Section 2 (Patch Management)
PCI DSS 4.06.3 (Vulnerability identification/action)Full process
SOC 2CC7.1 (Monitoring), CC8.1 (Change Management)Section 5, 6
ISMS-P2.10 (System/Service Security Management)All

8. Toolchain Recommendation

Essential tools

UseOSScommercial
image scanTrivy, GrypeSnyk, Prisma Cloud
OS ComplianceOpenSCAP, LynisQualys, Tenable
runtime securityFalcoSysdig Secure
Create SBOMSyft, TrivyAnchore
Secret ScanGitleaks, TruffleHogGitGuardian
SASTSemgrep, CodeQLSonarQube, Checkmarx
image signatureCosign (Sigstore)Docker Content Trust
Policy EngineOPA/Gatekeeper, KyvernoStyra DAS
코드 단계: Gitleaks (시크릿) + Semgrep (SAST)
빌드 단계: Trivy (이미지 스캔) + Syft (SBOM)
배포 단계: Cosign (이미지 서명) + Kyverno (정책)
런타임:   Falco (이상 탐지) + 감사 로그

9. Report template

Vulnerability Action Report

# 보안 취약점 조치 보고서

## 개요

- 보고일: 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. Actual inspection checklist

OS Security

  • Disable unnecessary services (systemctl list-unit-files --state=enabled)
  • Allow only SSH key-based authentication, block root login
  • Automatic security update settings
  • Firewall default deny policy
  • Activate audit log (auditd)
  • AIDE/OSSEC file integrity monitoring

Container Security

  • Use minimal base image (distroless/chainguard)
  • Remove build tools with multistage build
  • Run as non-root user
  • Read-only file system
  • Resource limits (CPU, memory, PID)
  • Image signature + verification

Kubernetes Security

  • PSA (Pod Security Admission) restricted mode
  • NetworkPolicy default deny-all
  • RBAC principle of least privilege
  • Etcd encryption
  • Enable audit logging
  • Secret external management (Vault, etc.)

Finish

Security is not a one-time action, but a continuous process. Summarize the core of this playbook in three lines.

  1. Automation: Prevent manual omission by embedding scan, patch, and verification into CI/CD.
  2. Layered defense: Establish an in-depth defense strategy that covers OS, image, runtime, and network.
  3. Response system: Repeat the cycle of discovery → classification → action → verification → reporting, and maintain SLA.

Perfect security is impossible, but through systematic operation risk can be reduced to a manageable level.

Quiz

Q1: What is the main topic covered in "Security vulnerability action playbook: OS package, container image, runtime hardening"?

We organize a practical security operation playbook that covers everything from CVE discovery to action, verification, and reporting, OS package vulnerability patching, container image security, and runtime hardening.

Q2: What is Entering? When a security scanner pours out a list of CVEs, it becomes difficult to know where to start. The important thing is not to immediately fix all vulnerabilities, but to have a process to prioritize based on risk, take systematic action, and prevent recurrence.

Q3: Explain the core concept of Runtime hardening. 4.1 Container runtime security Docker hardening


bash /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, "defa...

Q4: What are the key aspects of Playbook for each vulnerability response scenario?

Scenario 1: Critical CVE Emergency Patch

  [1시간] 자산 인벤토리에서 영향 범위 파악 [2시간] 패치 가용 여부 확인 ├── 패치 있음 → 스테이징 적용
  → 테스트 → 프로덕션 롤링 └── 패치 없음 → Workaround 적용 (WAF 룰, 설정 변경, 서비스 격리) [24시간]
  프로덕션 패치 완료 [48시간] 스캔으로 조치 검증 → 보고서 작성 [즉시] 알림 확인 (Falco, 감사 로그)
  [즉시]...

Q5: How does Toolchain Recommendation work? Essential tools Recommended minimum configuration


코드 단계: Gitleaks (시크릿) + Semgrep (SAST)
  빌드 단계: Trivy (이미지 스캔) + Syft (SBOM) 배포 단계: Cosign (이미지 서명) + Kyverno (정책)
  런타임: Falco (이상 탐지) + 감사 로그