2024-07-19,   Gun-ha, KANG

이번 포스팅에서는 Trivy를 사용하여 도커 및 기타 컨테이너 이미지의 취약성을 검사하는 방법을 공유해보려고 합니다.

개요

도커 컨테이너 이미지 스캔

  • 컨테이너를 프로덕션 환경에 배포하기 전에 취약점을 사전에 해결
  • 컨테이너화된 애플리케이션의 보안을 향상

Tools

  • Clair
  • Anchore Engine
  • Trivy

이 중 먼저, Aqura Security에서 만든 오픈소스 툴인 Trivy를 사용하여, 여러 대상 중 Container Image 관련 취약섬 검사에 대해서 공유

Trivy

Target (스캔할 수 있는 대상)

  • Container Image (해당 포스팅에서는 이 부분을 공유)
  • Filesystem
  • Rootfs
  • Git Repo (remote)
  • Virtual Machine Image
  • Kubernetes
  • AWS
  • SBOM

Scanner (찾을 수 있는 문제)

  • 사용 중인 OS 패키지와 소프트웨어 종속성 (SBOM)
  • 알려진 취약점 (CVE)
  • IaC 문제 및 구성오류
  • 민감 정보 및 비밀
  • 소프트웨어 라이선스

Mode

  • Standalone

1

  • Client/Server

    • Client
      • 독립 실행형으로 실행됨
      • 사용자가 명령어를 실행하면 로컬에서 바로 취약점 검사 수행
    • Server
      • 서버로 실행됨
      • 여러 클라이언트가 동시에 사용 가능하며, 중앙에서 취약점 DB를 관리할 수 있게 됨
        • 클라이언트는 이 서버에 요청을 보내 취약점 검사를 수행
        • 클라이언트는 취약점 DB를 다운받을 필요가 없어짐

2

Container Image

2가지 지원

  • 컨테이너 이미지 내부의 파일들
    • 컨테이너 이미지 내의 파일들을 스캔
  • 컨테이너 이미지의 메타데이터

컨테이너 이미지 내부의 파일 항목

  • Vulnerabilities (취약점)
  • Misconfigurations (구성 오류)
  • Secrets
  • Licenses
-- 해당 이미지에서 발견된 모든 취약점에 대한 보고서 생성
-- (Vulnerabilities + Secrets 은 디폴트로 활성화)
$ trivy image [IMAGE_NAME]

Vulnerabilities

  • Severity(심각도)
    • LOW : 0.1~3.9
    • MEDIUM : 4.0~6.9
    • HIGH : 7.0~8.9
    • CRITICAL : 9.0~10.0
-- 해당 옵션은 디폴트로 활성화된 상태
-- 스캔 범위를 취약점만으로 제한하는 등의 역할을 수행
$ trivy image --scanners vuln [IMAGE_NAME]

Misconfiguration

Infrastructure as Code(IaC) 파일들에 대한 구성 오류 검사

  • ex. Kubernetes Yaml
  • ex. Terraform 파일
$ trivy image --scanners misconfig [IMAGE_NAME]

Secrets

컨테이너 이미지 내부에서 민감한 정보나 비밀 데이터 탐지

  • 하드코딩된 비밀 정보
    • ex. API키, 패스워드, 데이터베이스 연결정보
  • 보안에 취약한 설정을 가진 파일이나 구성
    • ex. SSH 개인키가 포함된 경우, 파일 권한 설정 취약
  • 기타 민감한 데이터
$ trivy image [IMAGE_NAME]

Licenses

이미지에 포함된 패키지들의 라이선스 정보 검사 및 보고

  • 사용자가 해당 패키지를 사용할 때, 어떤 조건을 준수해야 하는지
$ trivy image --scanners license [IMAGE_NAME]

이미지 소스 검색 방식

저장된 이미지를 여러 위치에서 검색

  1. 로컬 Docker Engine
    • $ docker images
    • 로컬 도커 환경에서 저장된 이미지
  2. Containerd
    • $ nerdctl images
    • $ ctr image ls
    • 컨테이너 런타임에서 관리하는 이미지
  3. Podman
    • $ podman images
    • 도커와 유사한 컨테이너 관리 도구에서의 이미지
  4. 컨테이너 레지스트리
    • $ trivy image –remote docker.io/library/alpine:3.7.3
    • DockerHub, Github Container Registry 등 외부 레지스트
    • private Registry 포함한 Public/Private
  5. Tar Files
    • $ trivy image –input /path/to/image.tar
    • 로컬에 Tar로 저장된 이미지
  6. OCI(Open Container Initiative) Layout
    • $ trivy image –input /path/to/oci-layout
    • OCI는 컨테이너 포맷/런타임에 대한 오픈 스펙과 표준을 제공함으로써 컨테이너 생태계의 호환성을 강화하는 것
      • 이미지 스펙과 런타임스펙
-- 기본 동작 변경 시, --image-src 플래그 사용
-- 예시
$ trivy image --image-src podman,containerd [IMAGE_NAME]

테스트

1. Standalone Mode

  • command를 통해, python:3.4-alpine 이미지를 스캔
  • Standalone 모드이기에, 로컬에서 바로 취약점 검사 수행

docker-compose.yml

# https://aquasecurity.github.io/trivy/v0.53/getting-started/installation/

version: '3.3'

services:
  trivy:
    image: aquasec/trivy:0.53.0
    container_name: trivy
    volumes:
      - '/var/run/docker.sock:/var/run/docker.sock'
      # - '$HOME/Library/Caches:/root/.cache/' 
    command: ["image", "python:3.4-alpine"]
-- 4가지 모두 다 확인 
command: ["image", "--scanners", "vuln,secret,misconfig,license", "python:3.4-alpine"]
  • 실행 과정

    • 이 콘솔로그는 vuln과 secret에 대한 로그

      • secret 에 문제가 되는 코드는 없어서 로그가 안 뜨는 것으로 보임
1. 취약점 DB 업데이트 필요 확인
trivy  | 2024-07-18T06:44:32Z   INFO    Need to update DB

2. ghcr.io/aquasecurity/trivy-db:2 라는 취약점 DB 다운로드
trivy  | 2024-07-18T06:44:32Z   INFO    Downloading DB...       repository="ghcr.io/aquasecurity/trivy-db:2"

3. 취약점 스캐닝 활성화 확인
trivy  | 2024-07-18T06:44:36Z       INFO    Vulnerability scanning is enabled

4. 비밀 정보 스캐닝 활성화 확인
trivy  | 2024-07-18T06:44:36Z   INFO    Secret scanning is enabled

5. 스캐닝 속도 향상 권장사항 제공 (느리면, 비밀정보 비활성화해라 등)
trivy  | 2024-07-18T06:44:36Z   INFO    If your scanning is slow, please try '--scanners vuln' to disable secret scanning
trivy  | 2024-07-18T06:44:36Z   INFO    Please see also https://aquasecurity.github.io/trivy/v0.53/docs/scanner/secret#recommendation for faster secret detection

6. OS 감지 (컨테이너 이미지에서 사용된 OS와 버전 감지)
trivy  | 2024-07-18T06:44:38Z   INFO    Detected OS     family="alpine" version="3.9.2"

7. 취약점 감지
trivy  | 2024-07-18T06:44:38Z   INFO    [alpine] Detecting vulnerabilities...   os_version="3.9" repository="3.9" pkg_num=28

8. 언어별 파일 수 감지 (여기서는 파이썬 파일 하나있음을 감지)
trivy  | 2024-07-18T06:44:38Z   INFO    Number of language-specific files       num=1

9. 언어별 패키지(Bundler, npm, yarn ) 취약점 감지
trivy  | 2024-07-18T06:44:38Z   INFO    [python-pkg] Detecting vulnerabilities...

10. OS 지원 종료 경고
trivy  | 2024-07-18T06:44:38Z   WARN    This OS version is no longer supported by the distribution      family="alpine" version="3.9.2"
trivy  | 2024-07-18T06:44:38Z   WARN    The vulnerability detection may be insufficient because security updates are not provided

11. 결과 출력 형식 정보 제공 (디폴트 : 테이블 형식)
trivy  | 2024-07-18T06:44:38Z   INFO    Table result includes only package filenames. Use '--format json' option to get the full path to the package file.

12. 최종 스캔 결과 출력 (일부 출력)
(총 37개 중 4개가 낮은 심각도/16개의 중간심각도/13개의 높은 심각도/4개의 치명적 취약점 분류)
trivy  |
trivy  | python:3.4-alpine (alpine 3.9.2)
trivy  | ================================
trivy  | Total: 37 (UNKNOWN: 0, LOW: 4, MEDIUM: 16, HIGH: 13, CRITICAL: 4)
trivy  |
trivy  | ┌──────────────┬────────────────┬──────────┬────────┬───────────────────┬───────────────┬──────────────────────────────────────────────────────────────┐
trivy  | │   Library    │ Vulnerability  │ Severity │ Status │ Installed Version │ Fixed Version │                            Title                             │
trivy  | ├──────────────┼────────────────┼──────────┼────────┼───────────────────┼───────────────┼──────────────────────────────────────────────────────────────┤
trivy  | │ expat        │ CVE-2018-20843 │ HIGH     │ fixed  │ 2.2.6-r0          │ 2.2.7-r0      │ expat: large number of colons in input makes parser consume  │
trivy  | │              │                │          │        │                   │               │ high amount...                                               │
  • Status

    • fixed : 취약점이 패치된 버전이 존재하는 상태
    • not fixed : 취약점이 해결되지 않은 상태
    • unknown : 취약점 상태가 알려지지않은 상태
  • Fixed Version : 취약점이 패치된 버전

-- Lincense 보고서
-- 여기서는, OS 패키지 라이선스와 파이썬 패키지 라이선스 보고서

trivy  | OS Packages (license)
trivy  | =====================
trivy  | Total: 32 (UNKNOWN: 4, LOW: 15, MEDIUM: 2, HIGH: 11, CRITICAL: 0)
trivy  |
trivy  | ┌────────────────────────┬───────────────┬────────────────┬──────────┐
trivy  | │        Package         │    License    │ Classification │ Severity │
trivy  | ├────────────────────────┼───────────────┼────────────────┼──────────┤
trivy  | │ alpine-baselayout      │ GPL-2.0       │ restricted     │ HIGH     │
trivy  | ├────────────────────────┼───────────────┼────────────────┼──────────┤
trivy  | │ alpine-keys            │ MIT           │ notice         │ LOW      │
...
trivy  | Python (license)
trivy  | ================
trivy  | Total: 3 (UNKNOWN: 3, LOW: 0, MEDIUM: 0, HIGH: 0, CRITICAL: 0)
trivy  |
trivy  | ┌────────────┬─────────────┬────────────────┬──────────┐
trivy  | │  Package   │   License   │ Classification │ Severity │
trivy  | ├────────────┼─────────────┼────────────────┼──────────┤
trivy  | │ pip        │ MIT License │ unknown        │ UNKNOWN  │
trivy  | ├────────────┤             │                │          │
trivy  | │ setuptools │             │                │          │
trivy  | ├────────────┤             │                │          │
trivy  | │ wheel      │             │                │          │
trivy  | └────────────┴─────────────┴────────────────┴──────────┘
  • 옵션

    • timeout : 작업의 타임아웃
    • format : 출력형식
    • dependency-tree : 의존성 트리 포함여부
      • JSON 형식에서는 작동 X (JSON형식에서는 비활성화)
      • 출력을 table로 하면 가능함
    • list-all-pkgs : 모든 패키지 나열 설정
    • exit-code : 1 취약점이 발견되면 Trivy가 종료 코드를 1로 반환하도록 하는 설정
      • CI/CD 파이프라인에서 사용
    • output : 결과를 파일에 저장
    • scan : skip-dirs 특정 디렉토리를 스캔하지 않도록 설정
    • vulnerability: type : OS 및 라이브러리 취약점을 스캔하도록 설정
    • vulnerability: ignore-unfixed : 수정되지 않은 취약점을 무시하도록 설정
      • false : 모든 취약점 확인
    • db: skip-update 데이터베이스 업데이트를 건너뛰지 않도록 설정

2. Client/Server Mode

version: '3.3'

services:
  trivy-server:
    image: aquasec/trivy:0.53.0
    container_name: trivy-server
    command: ["server", "--listen", "0.0.0.0:8080"]
    ports:
      - "8081:8080"  # 외부포트 8081로 변경

  trivy-client:
    image: aquasec/trivy:0.53.0
    container_name: trivy-client
    depends_on:
      - trivy-server
    volumes:
      - '/var/run/docker.sock:/var/run/docker.sock'
    command: ["image", "--server", "http://trivy-server:8080", "python:3.4-alpine"]

3. Tar 파일로 이미지 스캔

$ docker images
$ docker save -o google_cadvisor.tar google/cadvisor:latest
$ vi docker-compose.yml

version: '3.3'

services:
  trivy:
    image: aquasec/trivy:0.53.0
    container_name: trivy
    volumes:
      - '/var/run/docker.sock:/var/run/docker.sock'
      - './volume/Library/Caches:/root/.cache/'
      - './google_cadvisor.tar:/google_cadvisor.tar'
    command: ["image", "--input", "/google_cadvisor.tar"]

4. 서비스를 올리면서, 올리는 서비스에 대한 이미지 분석 수행

version: '3.3'

services:
  app:
    image: alpine:latest
    container_name: alpine
    command: ["sh", "-c", "while true; do echo 'Hello from Alpine'; sleep 3600; done"]

  trivy:
    image: aquasec/trivy:0.53.0
    container_name: trivy
    volumes:
      - '/var/run/docker.sock:/var/run/docker.sock'
    entrypoint: ["sh", "-c", "trivy image alpine:latest"]
    depends_on:
      - app

실행 중인 컨테이너에 대한 실시간 스캔 X

참고


Contact Author. KangGunha Email. zxcvbnm9931@epozen.com

업데이트: