検索
連載

コンテナ/Kubernetesの脆弱性、機密情報、設定間違いが分かるOSS「Trivy」徹底解説〜もうイメージスキャンだけとは言わせないCloud Nativeチートシート(17)

Kubernetesやクラウドネイティブをより便利に利用する技術やツールの概要、使い方を凝縮して紹介する連載。今回は、コンテナ/Kubernetesの脆弱性、機密情報、設定間違いを診断、検出するOSS「Trivy」を紹介する(最新のv0.56.2含め2024年の情報に合うように更新)。

Share
Tweet
LINE
Hatena

 OSパッケージやライブラリ、アプリケーションで発見される脆弱(ぜいじゃく)性は日々増え続けていますが、皆さんのアプリケーション、システムは大丈夫でしょうか?

 日々最新のバージョンに修正して脆弱性を対処していれば問題ありませんが、インターネット上に転がっているサンプルなどを参考して実装した場合、「記事で利用されている古いバージョンをそのまま使用して脆弱性が混入してしまっている」なんてことがあるかもしれません。

 また、本連載でテーマにしているKubernetesでいえば、rootユーザーでコンテナを実行したり、rootファイルシステムを不必要に書き込み可能に設定したりして、「攻撃されやすいコンテナになってしまっている」なんてこともあり得ます。

 Kubernetesやクラウドネイティブをより便利に利用する技術やツールの概要、使い方を凝縮して紹介する本連載「Cloud Nativeチートシート」。今回は、そんなアプリケーションの脆弱性を手軽に検知してくれる「Trivy」を紹介します。

 Trivyは、リリース当初はコンテナイメージの脆弱性スキャンツールというイメージが強かったのですが、パッケージやライブラリ以外の脆弱性もスキャンできるようになっているので、その辺りも含めて紹介します。

Trivyとは

 Trivyはパッケージやライブラリの脆弱性をスキャンできるオープンソースソフトウェア(OSS)の診断ツールです。初期はコンテナイメージの脆弱性スキャンに特化していましたが、最近ではコンテナに限らずファイルシステムやGitリポジトリを対象にしたり、設定ファイルをスキャンして設定の問題点を確認したりすることもできます。

 特徴は、何よりシンプルであること。Goのシングルバイナリで提供されるため簡単にスキャンできますし、パイプラインへの組み込みも容易です。またスキャンは高速で、精度も評価されています。

 パッケージやライブラリの脆弱性スキャンツールは他にもありますが、使い勝手の良さなどから「多くの利用者に愛されている代表的なスキャンツール」といえます。


GitHub Starの比較(Trivy、Clair、Grype)

 Trivyは日本人のFukuda Teppei氏が個人で開発を進め、その功績が認められてAqua Securityに譲渡されたOSSです。Trivyの実装に着手した背景など分かりやすく記載されているので、興味のある方は同氏のブログもご確認ください。

 Trivyは「Harbor」「GitLab」「VMware Tanzu」のデフォルトのスキャナーとしても採用されています。もともと別のスキャナーを利用していたにもかかわらずTrivyに移行するという決断は、Trivyの有用性を示している事例だと思います。

 Trivyは精力的に新機能が開発されており、新しい機能が日々追加されていますが、本稿では、2024年10月の原稿執筆時点で最新のバージョン、v0.56.2を基に紹介します。

Trivyの主な機能

 下記表は、Trivyの主な機能です。

機能 内容 スキャン対象
1.脆弱性のスキャン CVE-IDが割り振られたパッケージやライブラリの脆弱性を検知する コンテナイメージ、ファイルシステム、Gitリポジトリ
2.設定ファイルのスキャン 推奨される設定と比較して設定の誤りや問題点を指摘する Terraform、Dockerfile、Kubernetesマニフェスト、AWS CloudFormation、Helmチャート
3.シークレット情報のスキャン ハードコーディングされた機密情報を検知する コンテナイメージ、ファイルシステム、Gitリポジトリ
4.Kubernetesクラスタのスキャン クラスタ内のリソースを対象にコンテナイメージの脆弱性スキャン、Kubernetesマニフェストのスキャン、シークレット情報のスキャンを行う Kubernetesクラスタ

1.脆弱性のスキャン

 TrivyはOSパッケージやアプリケーションの依存ライブラリをスキャンして、「CVE-ID」が割り振られた脆弱性を検知します。CVE-IDとは「CVE-YYYY-XXXX」の形式で割り振られる一意な脆弱性の識別番号です。ここ数年は割り振られるCVE-IDの件数が年々増加しており、2021年は2万件を超えました。このように日々新たな脆弱性が発見されるので、開発で利用しているパッケージやライブラリを定期的にスキャンすることが重要です。


脆弱性スキャンのイメージ図

 Trivyはコンテナイメージの脆弱性をスキャンするツールとしてユーザーを増やしてきましたが、現在はコンテナイメージに限らず、ホストマシン上のファイルシステムやGitリポジトリを対象にスキャンできます。

 v0.56.2では以下のOSパッケージをサポートしています。詳細はOS Packagesをご確認ください。「未修正の脆弱性検知」がNoの場合は、修正されたバージョンが存在するライブラリのみを検知します。

サポートOS
OS サポートバージョン パッケージマネージャー
Alpine Linux 2.2〜2.7、3.0〜3.16、edge apk
Wolfi Linux (n/a) apk
Chainguard (n/a) apk
Red Hat Enterprise Linux 6、7、8 dnf/yum/rpm
CentOS 6、7、8 dnf/yum/rpm
AlmaLinux 8、9 dnf/yum/rpm
Rocky Linux 8、9 dnf/yum/rpm
Oracle Linux 5、6、7、8 dnf/yum/rpm
Azure Linux(CBL-Mariner) 1.0、2.0、3.0 tdnf/dnf/yum/rpm
Amazon Linux 1、2、2023 yum/rpm
openSUSE Leap 42、15 zypper/rpm
openSUSE Tumbleweed (n/a) zypper/rpm
SUSE Linux Enterprise 11、12、15 zypper/rpm
SUSE Linux Enterprise Micro 5、6 zypper/rpm
Photon OS 1.0、2.0、3.0、4.0 tdnf/yum/rpm
Debian GNU/Linux 7、8、9、10、11、12 apt/dpkg
Ubuntu All versions supported by Canonical apt/apt-get/dpkg
OSs with installed Conda - conda

 アプリケーションの依存ライブラリのスキャンは以下の言語をサポートしています。詳細は「Language-specific Packages」をご確認ください。Trivyはスキャン対象から以下のようなファイルを探して依存ライブラリの情報を取得しています。スキャン対象やパッケージ管理方法の違いでスキャンの条件が変わることにご注意ください。

サポート言語
言語 ファイル Image/Rootfs Filesystem/Repository
Ruby Gemfile.lock -
gemspe -
Python Pipfile.lock -
poetry.lock -
requirements.txt -
egg package(\*.egg-info、\*.egg-info/PKG-INFO、\*.egg、EGG-INFO/PKG-INFO) -
wheel package(.dist-info/META-DATA) -
PHP composer.lock -
installed.json -
Node.js package-lock.json -
yarn.lock -
package.json -
.NET packages.lock.json
packages.config
.deps.json
\*Packages.props(Directory.Packages.props and legacy Packages.props file names are supported)
Java JAR、WAR、PAR、EAR(\*.jar、\*.war、\*.par、\*.ear) -
pom.xml -
\*gradle.lockfile -
\*.sbt.lock -
Go Binaries built with cargo-auditable -
go.mod -
Rust Cargo.lock
Binaries built with cargo-auditable -
C/C++ conan.lock -
Elixir mix.lock -
Dart pubspec.lock -
Swift Podfile.lock -
Package.resolved -
Julia Manifest.toml

 TrivyはスキャンしたOSパッケージやアプリケーションの依存ライブラリの情報を脆弱性のデータソースと突合することで、インストールされているパッケージやライブラリに脆弱性が含まれるかどうか教えてくれます。

2.設定ファイルのスキャン

 Trivyはv0.19.0から設定ファイルをスキャンできるようになりました。設定ファイルをスキャンすることで、設定誤りや見落としていた問題点を確認できます。現在は、次のような設定ファイルをスキャンできます。

  • Dockerfile
  • Kubernetesマニフェスト
  • Terraform
  • AWS CloudFormation
  • Helmチャート

 インターネット上に転がっているサンプルファイルはセキュリティを考慮していないものが多く、気付かないうちに脆弱な設定ファイルを作成している可能性があります。そのような場合にもTrivyのようなツールによるスキャンが効果的です。

 設定ファイルのスキャンでは、例えば次のような問題点を検知できます。

  • rootユーザーで実行されるDockerfile
  • 特権コンテナの起動が許されるKubernetesマニフェスト
  • 「Amazon S3」バケットが外部に公開されるTerraformコード

コラム Terraformスキャナー「tfsec」利用者はTrivyへの移行を推奨

 TerraformをスキャンするためのOSSスキャナー「tfsec」をご存じでしょうか?

 tfsecは以前はTrivyとは独立して開発されていましたが、tfsec v1.28.2の更新を最後に、以降の新機能はTrivyのみで開発されています。そのような事情があるので、TerraformやOpenTofuのスキャンにtfsecを利用されている方は、Trivyへの移行を推奨します。


3.シークレット情報のスキャン

 Trivyはv0.27.0からシークレット情報をスキャンできるようになりました。コンテナイメージやファイルシステムにハードコーディングされているシークレット情報を検知できます。

 現在は50以上のカテゴリーに対してシークレット情報を検知できます。例えば以下のようなものになります。

カテゴリー シークレット情報 重大度
AWS Access Key ID、Secret Access Key CRITICAL
Alibaba AccessKey ID、Secret Key HIGH
GCP Service Account CRITICAL
GitHub Personal Access Token、OAuth Access Token、App Token、Refresh Token CRITICAL
GitLab Personal Access Token CRITICAL
Slack Access Token HIGH
Webhook MEDIUM
Heroku API Key HIGH
npm Access Token CRITICAL

4.Kubernetesクラスタのスキャン

 Trivyでは、Kubernetesクラスタもスキャンできます。KubernetesのAPI Serverと通信することで、クラスタ内に存在するリソースを区別して次のようなスキャンが可能です。

  • スキャンの分類
    • Kubernetesクラスタ(api-server、kubeletなど)
    • クラスタ構成(Roles、ClusterRoles)
    • アプリケーションワークロード
  • スキャンの内容
    • 脆弱性
    • 設定誤り
    • シークレット情報


Trivyでできること、できないこと

 TrivyはCLIによる脆弱性の静的なスキャン(検知)が主な機能です。シンプルなスキャンが大きな特徴であり、Trivyのみではできないこともあります。例えば次のようなことはユーザーが考慮する必要があります。

  • スキャン結果をコンソールやファイルに出力できるが、商用のようなダッシュボードは用意されていないので可視化方法について検討する
  • 脆弱性の対処はユーザーの判断で進める。つまり運用プロセスを整備して対処方針を整理する
  • 基本的には静的なスキャンをサポートしているので、実行中のリソースをスキャンする場合は追加検討が必要(※ただし、Kubernetesを対象とする場合は実行中のリソースをスキャンする方法が幾つか提供されている)

 また、システム開発全体ではマルウェアやウイルスのスキャン、Webアプリケーションの脅威対策、アクセス制御などさまざまな観点でセキュリティの対策が必要です。「Trivyを入れれば全て解決する!」と考えずに、Trivyの使いどころを正しく理解した上で有効に利用するようにしましょう。

Trivyのセットアップ

動作条件

 TrivyはLinux、UNIX、macOS、WindowsといったOS上で動作します。

 公式マニュアルにインストール手順のないOSもあるので、最新のサポートOSはGitHubリポジトリのReleaesを参照してください。

Trivyのインストール

 TrivyはRPM(Red Hat Package Manager)やバイナリなどさまざまなインストール方法をサポートしています。Kubernetesでは「Helm Chart」も利用できますし、Dockerコンテナとして実行することもできます。

 ここでは公式ドキュメントで紹介されているインストールスクリプトを利用して、最新バージョンのTrivyのGoバイナリをLinux上にインストールします。

$ TRIVY_VERSION=$(curl -s "https://api.github.com/repos/aquasecurity/trivy/releases/latest" | grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/')
$ curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sudo sh -s -- -b /usr/local/bin v${TRIVY_VERSION}
aquasecurity/trivy info checking GitHub for tag 'v0.56.2'
aquasecurity/trivy info found version: 0.56.2 for v0.56.2/Linux/64bit
aquasecurity/trivy info installed /usr/local/bin/trivy
 
# v0.56.2を指定してインストールする場合
$ curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sudo sh -s -- -b /usr/local/bin v0.56.2
aquasecurity/trivy info checking GitHub for tag 'v0.56.2'
aquasecurity/trivy info found version: 0.56.2 for v0.56.2/Linux/64bit

 バージョンを確認します。

$ trivy -v
Version: 0.56.2
Vulnerability DB:
  Version: 2
  UpdatedAt: 2024-10-12 12:17:55.431066579 +0000 UTC
  NextUpdate: 2024-10-13 12:17:55.431066439 +0000 UTC
  DownloadedAt: 2024-10-12 15:10:37.876440539 +0000 UTC
Check Bundle:
  Digest: sha256:ae151c4eecf35c507d8f866121ddfbf46540b041bc7bca7cdd8d9f70ceb6f12c
  DownloadedAt: 2024-10-12 15:01:11.925420399 +0000 UTC

コンテナイメージのスキャン

 代表的な機能のコンテナイメージの脆弱性スキャンを試します。コンテナイメージのスキャンは「trivy image <イメージ名:イメージタグ>」の形式で実行します。

 ここではDocker Hubで公開されている少し古いPythonのイメージ(python:alpine3.13)をスキャンします。

$ trivy image python:alpine3.13
2024-10-13T04:58:16Z    INFO    [vuln] Vulnerability scanning is enabled
2024-10-13T04:58:16Z    INFO    [secret] Secret scanning is enabled
2024-10-13T04:58:16Z    INFO    [secret] If your scanning is slow, please try '--scanners vuln' to disable secret scanning
2024-10-13T04:58:16Z    INFO    [secret] Please see also https://aquasecurity.github.io/trivy/v0.56/docs/scanner/secret#recommendation for faster secret detection
2024-10-13T04:58:19Z    INFO    [python] License acquired from METADATA classifiers may be subject to additional terms  name="pip" version="21.2.4"
2024-10-13T04:58:19Z    INFO    [python] License acquired from METADATA classifiers may be subject to additional terms  name="setuptools" version="57.5.0"
2024-10-13T04:58:19Z    INFO    [python] License acquired from METADATA classifiers may be subject to additional terms  name="wheel" version="0.37.0"
2024-10-13T04:58:20Z    INFO    Detected OS     family="alpine" version="3.13.7"
2024-10-13T04:58:20Z    INFO    [alpine] Detecting vulnerabilities...   os_version="3.13" repository="3.13" pkg_num=36
2024-10-13T04:58:20Z    INFO    Number of language-specific files       num=1
2024-10-13T04:58:20Z    INFO    [python-pkg] Detecting vulnerabilities...
2024-10-13T04:58:20Z    WARN    This OS version is no longer supported by the distribution      family="alpine" version="3.13.7"
2024-10-13T04:58:20Z    WARN    The vulnerability detection may be insufficient because security updates are not provided
python:alpine3.13 (alpine 3.13.7)
Total: 36 (UNKNOWN: 0, LOW: 0, MEDIUM: 7, HIGH: 21, CRITICAL: 8)
┌-----------------------┬----------------┬----------┬--------┬-------------------┬------------------┬-------------------------------------------------------------┐
│        Library        │ Vulnerability  │ Severity │ Status │ Installed Version │  Fixed Version   │                            Title                            │
├-----------------------┼----------------┼----------┼--------┼-------------------┼------------------┼-------------------------------------------------------------┤
│ busybox               │ CVE-2022-28391 │ HIGH     │ fixed  │ 1.32.1-r7         │ 1.32.1-r8        │ busybox: remote attackers may execute arbitrary code if     │
│                       │                │          │        │                   │                  │ netstat is used                                             │
│                       │                │          │        │                   │                  │ https://avd.aquasec.com/nvd/cve-2022-28391                  │
│                       ├----------------┤          │        │                   ├------------------┼-------------------------------------------------------------┤
│                       │ CVE-2022-30065 │          │        │                   │ 1.32.1-r9        │ busybox: A use-after-free in Busybox's awk applet leads to  │
│                       │                │          │        │                   │                  │ denial of service...                                        │
│                       │                │          │        │                   │                  │ https://avd.aquasec.com/nvd/cve-2022-30065                  │
├-----------------------┼----------------┼----------┤        ├-------------------┼------------------┼-------------------------------------------------------------┤
│ expat                 │ CVE-2022-22822 │ CRITICAL │        │ 2.2.10-r1         │ 2.2.10-r2        │ expat: Integer overflow in addBinding in xmlparse.c         │
│                       │                │          │        │                   │                  │ https://avd.aquasec.com/nvd/cve-2022-22822                  │
│                       ├----------------┤          │        │                   │                  ├-------------------------------------------------------------┤
(略)
 
 Python (python-pkg)
Total: 4 (UNKNOWN: 0, LOW: 0, MEDIUM: 1, HIGH: 3, CRITICAL: 0)
┌-----------------------┬----------------┬----------┬--------┬-------------------┬---------------┬------------------------------------------------------------┐
│        Library        │ Vulnerability  │ Severity │ Status │ Installed Version │ Fixed Version │                           Title                            │
├-----------------------┼----------------┼----------┼--------┼-------------------┼---------------┼------------------------------------------------------------┤
│ pip (METADATA)        │ CVE-2023-5752  │ MEDIUM   │ fixed  │ 21.2.4            │ 23.3          │ pip: Mercurial configuration injectable in repo revision   │
│                       │                │          │        │                   │               │ when installing via pip                                    │
│                       │                │          │        │                   │               │ https://avd.aquasec.com/nvd/cve-2023-5752                  │
├-----------------------┼----------------┼----------┤        ├-------------------┼---------------┼------------------------------------------------------------┤
(略)
スキャン結果

 スキャン結果を見ると、コンテナイメージ内のOSパッケージとPythonの依存ライブラリの脆弱性が自動で検知され、件数が下記のように表示されました。脆弱性の件数は重大度(CRITICAL、HIGHなど)ごとに確認できます。今回はOSパッケージで36件の脆弱性が検知され、Pythonの依存ライブラリでは4件の脆弱性が検知されました。

# OSパッケージの脆弱性サマリー
python:alpine3.13 (alpine 3.13.7)
 
Total: 25 (UNKNOWN: 0, LOW: 0, MEDIUM: 5, HIGH: 10, CRITICAL: 10)
 
----------------------------------------------------------------------------
 
# Pythonの依存ライブラリの脆弱性サマリー
Python (python-pkg)
 
Total: 0 (UNKNOWN: 0, LOW: 0, MEDIUM: 0, HIGH: 0, CRITICAL: 0)

 テーブル形式で次のような脆弱性情報が表示されます。

項目 内容
Library パッケージやライブラリの名前
Vulnerability CVE-ID(脆弱性の識別番号)
Severity 重大度(CRITICAL / HIGH / MEDIUM / LOW / UNKNOWN)
Status 脆弱性のステータス(詳細はこちら
Installed Version インストールされているバージョン
Fixed Version 脆弱性が修正されたバージョン
Title 脆弱性の概要とAqua Vulnerability Database(AVD)のリンク

 今回は「busybox」で「CRITICAL」な脆弱性を確認できました。busyboxのバージョンを「1.32.1-r7」から「1.32.1-r8」に上げることで脆弱性を取り除くことができます。

 「Severity(重大度)」は影響の大きさをカテゴリー化したもので、脆弱性の脅威の度合いを把握するのに役立ちます。Trivyの「Severity(重大度)」はCVSS v3のスコアを基準として下記のように割り当てられます。なお、数値が大きいほど重大度を示します。

Severity(重大度) 脆弱性スコア
CRITICAL 9.0 - 10.0
HIGH 7.0 - 8.9
MEDIUM 4.0 - 6.9
LOW 0.1 - 3.9
UNKNOWN なし

 「Title」欄に記載されているAqua Vulnerability Database(AVD)のリンクを開くことで、検知した脆弱性の詳細をブラウザで確認できます。

コラム Aqua Vulnerability Database(AVD)とは

 AVDはAqua Securityが管理する脆弱性情報を公開するサイトです。脆弱性の情報はNational Vulnerability Database(NVD)やベンダーのセキュリティアドバイザリなどのさまざまなデータソースで管理されていますが、AVDは分散されているデータソースの情報を集約することで、1つのサイトで脆弱性情報をまとめて確認できます。

 Trivyのスキャン結果にはAVDのサイトへのリンクが埋め込まれています。そのリンクを開くと、下図のような画面が表示され、脆弱性の概要、脆弱性のスコア、影響するソフトウェア、脆弱性のデータソース、緩和策などの次アクションに役立つ情報を確認できます。脆弱性情報を検索することもできます。


AVDで表示される脆弱性情報

設定ファイルのスキャン

 設定ファイルのスキャンについて解説します。ここでは、コンテナとKubernetesに関係する次の2つの設定ファイルをスキャンします。


コラム Trivyのポリシー記述言語「Rego」

 Trivyは「Rego」で記述されたポリシーを利用して設定ファイルをスキャンします。

 Regoは汎用(はんよう)的なポリシー言語です。ポリシーを構成するルールをRegoで実装し、データの中身がルールに違反していないか検査することでOK/NGのような判定結果を出力できます。代表的なポリシーエンジン「Open Policy Agent」(OPA)はRegoで記述されたポリシーを利用しています。

 Trivyはデータ(設定ファイルの中身)をポリシー(Regoで実装された各設定ファイルの推奨設定)で検査し、設定の問題点を見つけます。ビルドインポリシーとしてRegoのポリシーがあらかじめ用意されているので、ユーザーは特殊な操作を必要とせずに設定ファイルをスキャンできます。Regoのポリシーをカスタマイズして自作ルールを適用することもできます。


1.Dockerfileのスキャン

 Dockerfileをスキャンします。ここでは、よくWeb上でサンプルとして公開されていそうな、次のような簡単なDockerfileを用意します。

# ベースイメージを指定
FROM alpine:latest
 
# nginxのインストール
RUN apk update && apk add --no-cache nginx
 
# 設定ファイルの配布
ADD default.conf /etc/nginx/http.d/default.conf
 
# nginxの実行
CMD nginx -g "daemon off;"
Dockerfile

 設定ファイルのスキャンは「trivy config <設定ファイル>」の形式で実行します。Dockerfileを指定してスキャンしてみます。

$ trivy config Dockerfile 
2024-10-12T12:32:17Z    INFO    [misconfig] Misconfiguration scanning is enabled
2024-10-12T12:32:20Z    INFO    Detected config files   num=1
 
Dockerfile (dockerfile)
 
Tests: 27 (SUCCESSES: 23, FAILURES: 4, EXCEPTIONS: 0)
Failures: 4 (UNKNOWN: 0, LOW: 2, MEDIUM: 1, HIGH: 1, CRITICAL: 0)
  
MEDIUM: Specify a tag in the 'FROM' statement for image 'alpine'
------------------------------------------------------------------------------------------------------------------------------------------------
When using a 'FROM' statement you should use a specific tag to avoid uncontrolled behavior when the image is updated.
 
See https://avd.aquasec.com/misconfig/ds001
------------------------------------------------------------------------------------------------------------------------------------------------
 Dockerfile:1
------------------------------------------------------------------------------------------------------------------------------------------------
   1 [ FROM alpine:latest
------------------------------------------------------------------------------------------------------------------------------------------------
 
 
HIGH: Specify at least 1 USER command inDockerfilewith non-root user as argument
------------------------------------------------------------------------------------------------------------------------------------------------
Running containers with 'root' user can lead to a container escape situation. It is a best practice to run containers as non-root users, which can be done by adding a 'USER' statement to the Dockerfile.
 
See https://avd.aquasec.com/misconfig/ds002
------------------------------------------------------------------------------------------------------------------------------------------------
 
LOW: Consider using 'COPY default.conf /etc/nginx/http.d/default.conf' command instead of 'ADD default.conf /etc/nginx/http.d/default.conf'
------------------------------------------------------------------------------------------------------------------------------------------------
You should use COPY instead of ADD unless you want to extract a tar file. Note that an ADD command will extract a tar file, which adds the risk of Zip-based vulnerabilities. Accordingly, it is advised to use a COPY command, which does not extract tar files.
 
See https://avd.aquasec.com/misconfig/ds005
------------------------------------------------------------------------------------------------------------------------------------------------
 Dockerfile:7
------------------------------------------------------------------------------------------------------------------------------------------------
   7 [ ADD default.conf /etc/nginx/http.d/default.conf
------------------------------------------------------------------------------------------------------------------------------------------------

 スキャン結果のサマリーが表示されています。27件のルールでスキャンして、4件が「Failures」として指摘されました。

Dockerfile (dockerfile)
 
Tests: 27 (SUCCESSES: 23, FAILURES: 4, EXCEPTIONS: 0)
Failures: 4 (UNKNOWN: 0, LOW: 2, MEDIUM: 1, HIGH: 1, CRITICAL: 0)

 続けて、Failuresの詳細が表示されています。下記のようにコードスニペットから指摘箇所を確認できたり、注釈から設定の修正方法を確認できたりします。

MEDIUM: Specify a tag in the 'FROM' statement for image 'alpine'
------------------------------------------------------------------------------------------------------------------------------------------------
When using a 'FROM' statement you should use a specific tag to avoid uncontrolled behavior when the image is updated.
 
See https://avd.aquasec.com/misconfig/ds001
------------------------------------------------------------------------------------------------------------------------------------------------
 Dockerfile:1
------------------------------------------------------------------------------------------------------------------------------------------------
   1 [ FROM alpine:latest
------------------------------------------------------------------------------------------------------------------------------------------------

 設定ファイルのスキャンに利用するRegoのポリシーはユニークなIDでルールが管理されています。コンテナイメージのスキャンと同様に、設定ファイルのスキャンでもAVDのリンクが表示されており、こちらのリンクをブラウザで開くことでIDを確認できます。


AVDのMisconfiguration表示画面

 Dockerfileのスキャンは「DS」から始まる3桁の数字で採番されたIDで管理されており、今回の3件のFailuresをまとめると下記のようになります。これらはいずれもDockerfileのベストプラクティスに従う指摘事項です。

ID 重大度 推奨設定の内容
DS001 MEDIUM コンテナイメージはlatestタグではなく特定のタグの付与を推奨
DS002 HIGH コンテナを非Rootユーザーで実行するようにDockerfileでuserステートメントの利用を推奨
DS005 LOW tarファイルを展開する必要がなければ、ADDではなくCOPYコマンドを推奨
DS026 LOW コンテナのヘルスチェック設定を推奨

 このように、特段意識せずに利用しているDockerfileにも脆弱な設定が潜んでいます。Trivyを利用することによって、脆弱な設定を検出するとともに、利用者にセキュリティ上注意する観点を喚起できます。

2.Kubernetesマニフェストのスキャン

 Kubernetesマニフェストをスキャンします。次のような、これまたなんの変哲もないKubernetesマニフェスト(deployment.yaml)を用意します。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-alpine
spec:
  selector:
    matchLabels:
      app: nginx-alpine
  replicas: 2
  template:
    metadata:
      labels:
        app: nginx-alpine
    spec:
      containers:
      - name: nginx-alpine
        image: nginx:alpine
        ports:
        - containerPort: 80
deployment.yaml

 TrivyのコマンドでKubernetesマニフェストをスキャンしてみます。

$ trivy config deployment.yaml
2024-10-13T05:26:51Z    INFO    [misconfig] Misconfiguration scanning is enabled
2024-10-13T05:26:56Z    INFO    Detected config files   num=1
 
deployment.yaml (kubernetes)
 
Tests: 94 (SUCCESSES: 80, FAILURES: 14, EXCEPTIONS: 0)
Failures: 14 (UNKNOWN: 0, LOW: 9, MEDIUM: 3, HIGH: 2, CRITICAL: 0)
 
MEDIUM: Container 'nginx-alpine' of Deployment 'nginx-alpine' should set 'securityContext.allowPrivilegeEscalation' to false
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
A program inside the container can elevate its own privileges and run as root, which might give the program control over the container and node.
 
See https://avd.aquasec.com/misconfig/ksv001
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 deployment.yaml:16-19
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  16 ┌       - name: nginx-alpine
  17 │         image: nginx:alpine
  18 │         ports:
  19 └         - containerPort: 80
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 
LOW: Container 'nginx-alpine' of Deployment 'nginx-alpine' should add 'ALL' to 'securityContext.capabilities.drop'
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
The container should drop all default capabilities and add only those that are needed for its execution.
See https://avd.aquasec.com/misconfig/ksv003
 
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 deployment.yaml:16-19
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  16 ┌       - name: nginx-alpine
  17 │         image: nginx:alpine
  18 │         ports:
  19 └         - containerPort: 80
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
(略)

 こちらは94件のルールでスキャンして、14件が「Failures」として指摘されました。Kubernetesマニフェストのスキャンでは「KSV」から始まるIDでルールが管理されており、検出結果をまとめると下記のようになりました。

ID 重大度 推奨設定の内容
KSV001 MEDIUM 「securityContext.allowPrivilegeEscalation」を「false」にして特権昇格を防ぐことを推奨
KSV003 LOW 「securityContext.capabilities.drop」を「all」にして実行に必要な最小権限を付与することを推奨
KSV011 LOW 「resources.limits.cpu」を設定してリソース枯渇による問題を防止することを推奨
KSV012 MEDIUM 「securityContext.runAsNonRoot」を「true」に設定して実行中のイメージを非Rootユーザーで実行させることを推奨
KSV014 LOW 「securityContext.readOnlyRootFilesystem」を「true」に設定してファイルシステムの改ざんやファイルの書き込みを防止して侵入を制限することを推奨
KSV015 LOW 「resources.requests.cpu」を設定してPodを配置するスケジューラーがより適切に判断を下せることを推奨
KSV016 LOW 「resources.requests.memory」を設定してPodを配置するスケジューラーがリソース競合時の対処を適切に判断できるようにすることを推奨
KSV018 LOW 「resources.limits.memory」を設定してリソース枯渇による問題を防止することを推奨
KSV020 LOW 「securityContext.runAsUser」を10000より大きな値に設定してホストユーザーテーブルとの競合を避けることを推奨
KSV021 LOW 「securityContext.runAsGroup」を10000より大きな値に設定してホストグループテーブルとの競合を避けることを推奨
KSV030 LOW 「securityContext.seccompProfile.type」をPodまたはコンテナのどちらかで「RuntimeDefault」にすることを推奨
KSV104 LOW Seccompプロファイルを指定することを推奨
KSV106 LOW コンテナは全てのcapabilitiesをdropし、NET_BIND_SERVICEのcapabilitiesのみ許可することを推奨
KSV117 HIGH spec.template.spec.containers.ports.containerPortは1024未満にしないことを推奨

 こちらもKubernetesマニフェストを設定する際に意識した方がよい内容が指摘されています。簡易な動作確認であれば気にしなくてよいと思いますが、本番環境で動かす際には上記のような指摘に対する設計方針を整理して進めることが望ましいでしょう。

コラム TrivyのRegoポリシーと「Pod Security Standards」

 KubernetesはPodのセキュリティ関連のベストプラクティスへ対応するために、「Pod Security Standards」(PSS)を公開しています。PSSはKubernetesが考えるセキュリティ対策の基本方針であり、標準的なセキュリティ対策方針「Baseline」と、よりセキュリティを強化する方針「Restricted」の2つのポリシーが用意されています。

 TrivyのRegoのポリシーは、PSSの「Baseline」と「Restricted」のポリシーに準拠する方針で提供されています。例えば、上記のKubernetesマニフェストスキャン結果では、「KSV001」「KSV012」は、「Restricted」に準拠するルールとして管理されています。

 一方、TrivyはPSSの観点だけでなく、Kubernetesマニフェストの推奨設定として独自のポリシーも提供しています。例えば、ユーザーが作成したPodをkube-systemのNamespaceにデプロイすることを問題として指摘してくれます。

 ポリシーの詳細は公式のリポジトリをご確認ください。


ディレクトリを指定した複数ファイルのスキャン

 Trivyはディレクトリを指定することで複数のファイルを同時にスキャンできます。設定ファイルを自動で識別するので、次のようにDockerfileとKubernetesマニフェストを同じディレクトリに配置しても問題なくスキャンできます。

$ ls ./conf
deployment.yaml  Dockerfile
 
$ trivy config ./conf
2022-06-20T17:42:00.451Z        INFO    Misconfiguration scanning is enabled
2022-06-20T17:42:01.027Z        INFO    Detected config files: 2
 
Dockerfile (dockerfile)
 
Tests: 22 (SUCCESSES: 19, FAILURES: 3, EXCEPTIONS: 0)
Failures: 3 (UNKNOWN: 0, LOW: 1, MEDIUM: 1, HIGH: 1, CRITICAL: 0)
 
(略)
 
deployment.yaml (kubernetes)
 
Tests: 34 (SUCCESSES: 22, FAILURES: 12, EXCEPTIONS: 0)
Failures: 12 (UNKNOWN: 0, LOW: 10, MEDIUM: 2, HIGH: 0, CRITICAL: 0)
 
(略)

シークレット情報のスキャン

 コンテナイメージに含まれるシークレット情報をスキャンするには、シークレット情報を含むコンテナイメージを用意する必要があります。

 まずGitHubのパーソナルアクセストークンが記載されている「secret.txt」を用意します。

# ghp_7gTUtmVZrL5fdz2wbR6LLxuw5zgjuzLhKBNf
ghp_393pk5rdnTKwVgXp69aZap6KV8KAr9cSiE5d
secret.txt

 secret.txtをコンテナイメージ内に配置します。

# ベースイメージを指定
FROM alpine:latest
 
# nginxのインストール
RUN apk update && apk add --no-cache nginx
 
# 設定ファイルの配布
ADD default.conf /etc/nginx/http.d/default.conf
 
# シークレット情報が記載されたファイルを配置
COPY secret.txt .
 
# nginxnの実行
CMD nginx -g "daemon off;"
Dockerfile

 コンテナイメージをビルドします。

$ docker build . -t nginx-secret:v1

 コンテナイメージをスキャンします。

$ trivy image nginx-secret:v1
2022-06-20T17:43:51.339Z        INFO    Vulnerability scanning is enabled
2022-06-20T17:43:51.339Z        INFO    Secret scanning is enabled
2022-06-20T17:43:51.339Z        INFO    If your scanning is slow, please try '--security-checks vuln' to disable secret scanning
2022-06-20T17:43:51.339Z        INFO    Please see also https://aquasecurity.github.io/trivy/v0.29.1/docs/secret/scanning/#recommendation for faster secret detection
2022-06-20T17:43:51.617Z        INFO    Detected OS: alpine
2022-06-20T17:43:51.617Z        INFO    Detecting Alpine vulnerabilities...
2022-06-20T17:43:51.619Z        INFO    Number of language-specific files: 0
 
nginx-secret:v1 (alpine 3.16.0)
 
Total: 0 (UNKNOWN: 0, LOW: 0, MEDIUM: 0, HIGH: 0, CRITICAL: 0)
 
 
/secret.txt (secrets)
 
Total: 2 (UNKNOWN: 0, LOW: 0, MEDIUM: 0, HIGH: 0, CRITICAL: 2)
 
┌----------┬------------------------------┬----------┬---------┬---------┐
│ Category │         Description          │ Severity │ Line No │  Match  │
├----------┼------------------------------┼----------┼---------┼---------┤
│  GitHub  │ GitHub Personal Access Token │ CRITICAL │    1    │ # ***** │
│          │                              │          ├---------┼---------┤
│          │                              │          │    2    │ *****   │
└----------┴------------------------------┴----------┴---------┴---------┘

 シークレット情報が含まれるファイル名(secret.txt)と、詳細な情報がテーブル形式で出力されました。

項目 内容
Category シークレット情報のカテゴリー(AWS、GitHubなど)
Description 各カテゴリーのシークレット情報
Severity 重大度(CRITICAL、HIGH、MEDIUM、LOW)
Line No シークレット情報を検知した行数
Match シークレット情報をマスクして表示

 今回はハードコーディングされたGitHubのパーソナルアクセストークンを検知できました。TrivyはGitHubのパーソナルアクセストークン以外にもさまざまなカテゴリーのシークレット情報をスキャンできます。詳細はこちらをご確認ください。

 今回のGitHubのパーソナルアクセストークンは、正規表現「ghp_[0-9a-zA-Z]{36}」の文字列を検知するルールがあらかじめ用意されているので、シークレット情報として検知できました。詳細な検知ルールが気になる方は、ビルトインルールをご覧ください。

 デフォルトでは「allow-rule」も適用されます。コンテナイメージ内のシークレット情報が特定のファイル名やディレクトリ配下に格納されている場合は検知対象外となることにご注意ください。例えば、シークレット情報が記載されたファイルが以下のようなファイル名やディレクトリ配下に配置されているとシークレット情報として検知されません。

  • 「-test」が含まれるファイル名
    • hoge-testsecret.txt
    • secret-test.txt
  • 「.md」の拡張子であるマークダウン形式のファイル名
    • secret.md
  • 「/vendor/」ディレクトリ配下のファイル
    • /vendor/secret.txt


Kubernetesクラスタのスキャン

 ここまでコンテナイメージ、設定ファイル、シークレット情報のスキャンを説明してきましたが、これらは静的な解析です。コンテナイメージをデプロイした後に、新たな脆弱性が発見されることもありますし、Trivyによるチェックを受けていないマニフェスト、イメージが勝手にデプロイされることもあり得ます。

 TrivyのKubernetesクラスタスキャンの機能を利用すると、動作しているクラスタ環境から脆弱性を検出することができます。

 現在は次のような2つの観点でスキャン結果を確認できます。

 順番にKubernetesクラスタのスキャンを試します。

事前準備

 クラスタ構築の流れは省略しますが、今回は「Google Kubernetes Engine」(GKE)クラスタを対象にスキャンしてみます。

 まずはTrivyの実行環境からKubernetesクラスタに接続できるように、kubeconfigファイルを用意して「kubectl」コマンドでKubernetesクラスタと接続できるようにしておきましょう。今回は「~/.kube/config」の認証情報でGKEクラスタに接続する環境を用意し、Trivyを実行します。

 「2.Kubernetesマニフェストのスキャン」で作成したKubernetesマニフェスト(deployment.yaml)を「default」のNamespaceにデプロイしておきます。

$ kubectl apply -f deployment.yaml

 Deploymentリソースの「nginx-alpine」が作成されました。

$ kubectl get deployment
NAME           READY   UP-TO-DATE   AVAILABLE   AGE
nginx-alpine   2/2     2            2           8s

1.Kubernetesクラスタの脆弱性レポート

 Kubernetesクラスタ内のリソースの脆弱性や指摘事項を俯瞰(ふかん)的に確認する方法を紹介します。

 Kubernetesクラスタのスキャンは下記のような形式で実行します。ここでは、defaultネームスペース(--include-namespaces default)のワークロードのスキャンのみ(--disable-node-collector)を実行します。

$ trivy k8s --include-namespaces default --disable-node-collector --report all
(略)
namespace: default, deployment: nginx-alpine (kubernetes)
 
Tests: 94 (SUCCESSES: 79, FAILURES: 15, EXCEPTIONS: 0)
Failures: 15 (UNKNOWN: 0, LOW: 10, MEDIUM: 3, HIGH: 2, CRITICAL: 0)
 
MEDIUM: Container 'nginx-alpine' of Deployment 'nginx-alpine' should set 'securityContext.allowPrivilegeEscalation' to false
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
A program inside the container can elevate its own privileges and run as root, which might give the program control over the container and node.
 
See https://avd.aquasec.com/misconfig/ksv001
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 namespace: default, deployment: nginx-alpine:18-21
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  18 ┌                 - image: nginx:alpine
  19 │                   name: nginx-alpine
  20 │                   ports:
  21 └                     - containerPort: 80
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 
LOW: Container 'nginx-alpine' of Deployment 'nginx-alpine' should add 'ALL' to 'securityContext.capabilities.drop'
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
The container should drop all default capabilities and add only those that are needed for its execution.
 
See https://avd.aquasec.com/misconfig/ksv003
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 namespace: default, deployment: nginx-alpine:18-21
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  18 ┌                 - image: nginx:alpine
  19 │                   name: nginx-alpine
  20 │                   ports:
  21 └                     - containerPort: 80
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 このように、Kubernetesクラスタで実行中のDeploymentリソースに対して脆弱性をスキャンできました。しかし、1つのDeploymentリソースでもこれほど多くの脆弱性がスキャンされるため、全体像を把握するのが難しくなります。

2.Kubernetesリソースの脆弱性詳細

 そこで、次は「--report summary」を指定して実行してみましょう。

$ trivy k8s --include-namespaces default --disable-node-collector --report summary
(略)
Summary Report for [cluster name]
Workload Assessment
┌-----------┬-------------------------┬-------------------┬--------------------┬-------------------┐
│ Namespace │        Resource         │  Vulnerabilities  │ Misconfigurations  │      Secrets      │
│           │                         ├---┬---┬---┬---┬---┼---┬---┬---┬----┬---┼---┬---┬---┬---┬---┤
│           │                         │ C │ H │ M │ L │ U │ C │ H │ M │ L  │ U │ C │ H │ M │ L │ U │
├-----------┼-------------------------┼---┼---┼---┼---┼---┼---┼---┼---┼----┼---┼---┼---┼---┼---┼---┤
│ default   │ Deployment/nginx-alpine │   │   │   │   │   │   │ 2 │ 3 │ 10 │   │   │   │   │   │   │
└-----------┴-------------------------┴---┴---┴---┴---┴---┴---┴---┴---┴----┴---┴---┴---┴---┴---┴---┘
Severities: C=CRITICAL H=HIGH M=MEDIUM L=LOW U=UNKNOWN
Infra Assessment
┌-----------┬----------┬-------------------┬-------------------┬-------------------┐
│ Namespace │ Resource │  Vulnerabilities  │ Misconfigurations │      Secrets      │
│           │          ├---┬---┬---┬---┬---┼---┬---┬---┬---┬---┼---┬---┬---┬---┬---┤
│           │          │ C │ H │ M │ L │ U │ C │ H │ M │ L │ U │ C │ H │ M │ L │ U │
└-----------┴----------┴---┴---┴---┴---┴---┴---┴---┴---┴---┴---┴---┴---┴---┴---┴---┘
Severities: C=CRITICAL H=HIGH M=MEDIUM L=LOW U=UNKNOWN
RBAC Assessment
┌-----------┬----------┬-------------------┐
│ Namespace │ Resource │  RBAC Assessment  │
│           │          ├---┬---┬---┬---┬---┤
│           │          │ C │ H │ M │ L │ U │
└-----------┴----------┴---┴---┴---┴---┴---┘
Severities: C=CRITICAL H=HIGH M=MEDIUM L=LOW U=UNKNOWN

 このように、3種類のAssessmentサマリーとして表示されるので脆弱性の全体像を把握しやすくなりました。

  • Workload Assessment
    クラスタ内のアプリケーションリソースを対象に脆弱性をスキャン
  • Infra Assessment
    クラスタのインフラコンポーネントを対象に脆弱性をスキャン
  • RBAC Assessment
    クラスタ設定に関して脆弱性をスキャン

 NamespacesのFlags設定に加えて、下記のようなFlagsを利用することで、より柔軟にスキャンできます。

  • --skip-images
    クラスタリソースのイメージスキャンをスキップできる
  • --include-kindsまたは--exclude-kinds
    スキャン対象のリソースを柔軟に指定できる
  • --severity
    重大度でフィルタリングできる
  • --scanner
    スキャンしたい脆弱性のタイプを指定できる
  • --format
    テーブルやJSON形式で結果を出力できる

Trivy CLIの主なオプション

 Trivyはどれもシンプルなコマンドでスキャンできることが分かりました。一方で、さまざまなCLIのコマンドオプションが用意されており、利用方法に応じて結果をカスタマイズできます。

 ここでは主にコンテナイメージのスキャンに有効なCLIのコマンドオプションを中心に紹介します。

脆弱性をフィルタリングする

・未修正の脆弱性を検知対象外とする

 Trivyは未修正の脆弱性を検知する場合があります。未修正の脆弱性を検知した場合、ライブラリを最新バージョンにアップデートしても対処できませんが、Web Application Firewall(WAF)やファイアウォールなど別の設定で緩和できる可能性があります。一方で検知されても対処しないなら、必要なものだけ検知するように未修正の脆弱性を検知対象外とすることもできます。未修正の脆弱性を検知したくない場合は「--ignore-unfixed」オプションを使用します。

# 未修正の脆弱性を含む
$ trivy image ruby:2.4.0
ruby:2.4.0 (debian 8.7)
=======================
Total: 8602 (UNKNOWN: 67, LOW: 3108, MEDIUM: 3021, HIGH: 1932, CRITICAL: 474)
 
# 未修正の脆弱性を対象外とする
$ trivy image --ignore-unfixed ruby:2.4.0
 
ruby:2.4.0 (debian 8.7)
=======================
Total: 3755 (UNKNOWN: 66, LOW: 130, MEDIUM: 2077, HIGH: 1147, CRITICAL: 335)

・重大度でフィルタリングする

 重大度を指定して検知したい場合は、先述の「--severity」オプションを使用します。次の例では重大度が「HIGH」「CRITICAL」の脆弱性のみ検知されます。

$ trivy image --severity HIGH,CRITICAL python:alpine3.13
 
python:alpine3.13 (alpine 3.13.7)
 
Total: 20 (HIGH: 10, CRITICAL: 10)

・指定したCVE-IDを検知対象外とする

 「.trivyignore」という名前のファイルにCVE-IDを記述することで、特定の脆弱性を検知対象外にできます。次の例では、「CVE-2022-22822」を検知対象外としています。

# 「CVE-2022-22822」が検知される
$ trivy image python:alpine3.13
 
python:alpine3.13 (alpine 3.13.7)
 
Total: 25 (UNKNOWN: 0, LOW: 0, MEDIUM: 5, HIGH: 10, CRITICAL: 10)
 
┌--------------┬----------------┬----------┬-------------------┬---------------┬-------------------------------------------------------------┐
│   Library    │ Vulnerability  │ Severity │ Installed Version │ Fixed Version │                            Title                            │
├--------------┼----------------┼----------┼-------------------┼---------------┼-------------------------------------------------------------┤
│ busybox      │ CVE-2022-28391 │ CRITICAL │ 1.32.1-r7         │ 1.32.1-r8     │ busybox: remote attackers may execute arbitrary code if     │
│              │                │          │                   │               │ netstat is used                                             │
│              │                │          │                   │               │ https://avd.aquasec.com/nvd/cve-2022-28391                  │
├--------------┼----------------┼----------┼-------------------┼---------------┼-------------------------------------------------------------┤
│ expat        │ CVE-2022-22822 │ CRITICAL │ 2.2.10-r1         │ 2.2.10-r2     │ expat: Integer overflow in addBinding in xmlparse.c         │
│              │                │          │                   │               │ https://avd.aquasec.com/nvd/cve-2022-22822                  │
│              ├----------------┤          │                   │               ├-------------------------------------------------------------┤
│              │ CVE-2022-22823 │          │                   │               │ expat: Integer overflow in build_model in xmlparse.c        │
│              │                │          │                   │               │ https://avd.aquasec.com/nvd/cve-2022-22823                  │
│              ├----------------┤          │                   │               ├-------------------------------------------------------------┤
 
(略)

 「.trivyignore」ファイルにCVE-IDを記入します。

# 検知対象外とするCVE-ID
CVE-2022-22822
.trivyignore

 再度スキャンすると「CVE-2022-22822」は検知されなくなりました。

# 「CVE-2022-22822」が検知されなくなる
$ trivy image python:alpine3.13
 
python:alpine3.13 (alpine 3.13.7)
 
Total: 24 (UNKNOWN: 0, LOW: 0, MEDIUM: 5, HIGH: 10, CRITICAL: 9)
 
┌--------------┬----------------┬----------┬-------------------┬---------------┬-------------------------------------------------------------┐
│   Library    │ Vulnerability  │ Severity │ Installed Version │ Fixed Version │                            Title                            │
├--------------┼----------------┼----------┼-------------------┼---------------┼-------------------------------------------------------------┤
│ busybox      │ CVE-2022-28391 │ CRITICAL │ 1.32.1-r7         │ 1.32.1-r8     │ busybox: remote attackers may execute arbitrary code if     │
│              │                │          │                   │               │ netstat is used                                             │
│              │                │          │                   │               │ https://avd.aquasec.com/nvd/cve-2022-28391                  │
├--------------┼----------------┼----------┼-------------------┼---------------┼-------------------------------------------------------------┤
│ expat        │ CVE-2022-22823 │ CRITICAL │ 2.2.10-r1         │ 2.2.10-r2     │ expat: Integer overflow in build_model in xmlparse.c        │
│              │                │          │                   │               │ https://avd.aquasec.com/nvd/cve-2022-22823                  │
│              ├----------------┤          │                   │               ├-------------------------------------------------------------┤
│              │ CVE-2022-22824 │          │                   │               │ expat: Integer overflow in defineAttribute in xmlparse.c    │
│              │                │          │                   │               │ https://avd.aquasec.com/nvd/cve-2022-22824                  │
│              ├----------------┤          │                   ├---------------┼-------------------------------------------------------------┤
 
(略)

 なお、「--ignorefile」オプションを使用すると、任意の名前のファイルで上記のように設定できます。

・OSパッケージまたはアプリケーションの依存ライブラリのみをスキャンする

 「--pkg-types」オプションを利用すると、特定の脆弱性タイプを対象にできます。OSパッケージのみをスキャンする場合は「os」、アプリケーションの依存ライブラリのみをスキャンする場合は「library」を指定します。スキャンに時間がかかる場合は、変更箇所のみを対象にするためにこの設定を検討するとよいでしょう。

# OSパッケージのみ対象
$ trivy image --pkg-type os python:alpine3.13
python:alpine3.13 (alpine 3.13.7)
Total: 34 (UNKNOWN: 0, LOW: 0, MEDIUM: 7, HIGH: 19, CRITICAL: 8)
# アプリケーションの依存ライブラリのみ対象
$ trivy image --pkg-type library python:alpine3.13
Python (python-pkg)
Total: 4 (UNKNOWN: 0, LOW: 0, MEDIUM: 1, HIGH: 3, CRITICAL: 0)

・スキャナーをフィルタリングする

 「--scanners」でスキャンの種類を選択できます。デフォルトでは「vuln,secret」が指定されており、「vuln」はコンテナイメージの脆弱性、「secret」はシークレット情報をそれぞれスキャンします。つまり、デフォルト設定ではコンテナイメージの脆弱性スキャンとシークレット情報のスキャンが同時に行われます。

 シークレット情報のスキャンを除外したい場合は、「vuln」を明示的に指定します。これにより、スキャンの速度も向上します。以下の例では、「シークレット情報のスキャン」で作成したコンテナイメージ(nginx-secret)を対象にスキャンを実行し、シークレット情報が検出されないことを確認しています。

$ trivy image --scanners vuln nginx-secret:v1
nginx-secret:v1 (alpine 3.20.3)
Total: 0 (UNKNOWN: 0, LOW: 0, MEDIUM: 0, HIGH: 0, CRITICAL: 0)

出力フォーマットをカスタマイズする

 コンテナイメージのスキャン結果のデフォルトは「Table」形式で表示されますが、さまざまなフォーマットでスキャン結果を表示できます。

フォーマット 特徴
Table デフォルトはテーブル形式
JSON JSON形式で出力、テーブル形式より詳細な脆弱性情報を確認可能
SARIF GitHub上のスキャンで使用できるフォーマット
Template Templateファイルを利用することで下記のような複数のフォーマットをサポート
1.カスタム:Sprig関数を利用したカスタマイズ形式で出力
2.ASFF:「AWS Security Hub」に連携可能なフォーマットで出力
3.HTML:HTML形式で出力
4.XML:XML形式で出力
SBOM CycloneDXとSPDX形式に対応したフォーマット
GitHub dependency snapshot GitHub上で依存関係をレビューするフォーマット

 なお、TemplateファイルはTrivyをRPMでインストールすることで「/usr/local/share/trivy/templates」に自動的に配置されます。Trivyのインストール方法の違いでTemplateファイルの利用可否が異なるのでご注意ください。

・JSONフォーマット

 「--format」オプションでフォーマットを指定します。JSONフォーマットの出力例は下記のようになります。なお、「--output」オプションを使用してファイルに出力しています。

$ trivy image --format json --output results.json python:alpine3.13

 results.jsonの一部を確認してみます。

---
  "Results": [
    {
      "Target": "python:alpine3.13 (alpine 3.13.7)",
      "Class": "os-pkgs",
      "Type": "alpine",
      "Vulnerabilities": [
        {
          "VulnerabilityID": "CVE-2022-28391",
          "PkgName": "busybox",
          "InstalledVersion": "1.32.1-r7",
          "FixedVersion": "1.32.1-r8",
          "Layer": {
            "Digest": "sha256:5758d4e389a3f662e94a85fb76143dbe338b64f8d2a65f45536a9663b05305ad",
            "DiffID": "sha256:7fcb75871b2101082203959c83514ac8a9f4ecfee77a0fe9aa73bbe56afdf1b4"
          },
          "SeveritySource": "nvd",
          "PrimaryURL": "https://avd.aquasec.com/nvd/cve-2022-28391",
          "DataSource": {
            "ID": "alpine",
            "Name": "Alpine Secdb",
            "URL": "https://secdb.alpinelinux.org/"
          },
          "Title": "busybox: remote attackers may execute arbitrary code if netstat is used",
          "Description": "BusyBox through 1.35.0 allows remote attackers to execute arbitrary code if netstat is used to print a DNS PTR record's value to a VT compatible terminal. Alternatively, the attacker could choose to change the terminal's colors.",
          "Severity": "CRITICAL",
          "CVSS": {
            "nvd": {
              "V2Vector": "AV:N/AC:L/Au:N/C:P/I:P/A:P",
              "V3Vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
              "V2Score": 7.5,
              "V3Score": 9.8
            },
            "redhat": {
              "V3Vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:N",
              "V3Score": 6.5
            }
          },
          "References": [
            "https://access.redhat.com/security/cve/CVE-2022-28391",
            "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-28391",
            "https://git.alpinelinux.org/aports/plain/main/busybox/0001-libbb-sockaddr2str-ensure-only-printable-characters-.patch",
            "https://git.alpinelinux.org/aports/plain/main/busybox/0002-nslookup-sanitize-all-printed-strings-with-printable.patch",
            "https://gitlab.alpinelinux.org/alpine/aports/-/issues/13661",
            "https://nvd.nist.gov/vuln/detail/CVE-2022-28391"
          ],
          "PublishedDate": "2022-04-03T21:15:00Z",
          "LastModifiedDate": "2022-04-12T17:31:00Z"
        },
---
results.json

パッケージ一覧を出力する

 「--list-all-pkgs」オプションを指定すると、脆弱性に関係なくインストールされているパッケージの一覧を出力できます。注意点としてフォーマットをJSONにする必要があります。パッケージの一覧を確認することでソフトウェアの構成情報の管理に役立ちます。

$ trivy image --list-all-pkgs --format json -o pkgs-list.json python:alpine3.13

 pkgs-list.jsonの一部を確認します。

---
  "Results": [
    {
      "Target": "python:alpine3.13 (alpine 3.13.7)",
      "Class": "os-pkgs",
      "Type": "alpine",
      "Packages": [
        {
          "Name": ".python-rundeps",
          "Version": "20211113.034814",
          "Layer": {
            "Digest": "sha256:35d95eb0acaf68d870f4a0e1bb58d7ae9fc2c3b76b2a6f0827423e5099e19c9d",
            "DiffID": "sha256:01640cf05d16090f4146ede8b3bfb5d8c3ed55c2f74e06114bd5478beea0a764"
          }
        },
        {
          "Name": "alpine-baselayout",
          "Version": "3.2.0-r8",
          "SrcName": "alpine-baselayout",
          "SrcVersion": "3.2.0-r8",
          "License": "GPL-2.0-only",
          "Layer": {
            "Digest": "sha256:5758d4e389a3f662e94a85fb76143dbe338b64f8d2a65f45536a9663b05305ad",
            "DiffID": "sha256:7fcb75871b2101082203959c83514ac8a9f4ecfee77a0fe9aa73bbe56afdf1b4"
          }
        },
        {
          "Name": "alpine-keys",
          "Version": "2.4-r0",
          "SrcName": "alpine-keys",
          "SrcVersion": "2.4-r0",
          "License": "MIT",
          "Layer": {
            "Digest": "sha256:5758d4e389a3f662e94a85fb76143dbe338b64f8d2a65f45536a9663b05305ad",
            "DiffID": "sha256:7fcb75871b2101082203959c83514ac8a9f4ecfee77a0fe9aa73bbe56afdf1b4"
          }
        },
---
pkgs-list.json

脆弱性検知時の終了コードを指定する

 「--exit-code」オプションを「1」に指定すると、脆弱性を検知したときに終了コードが「1」になります。これはパイプラインを停止させたいときに役立ちます。例えば、--severityオプションでCRITICALの脆弱性をスキャンしつつ、--exit-codeを1に指定すると、CRITICALの脆弱性を検知したときに終了コードが1となり、終了コードが1になることでパイプラインを止めることができます。これによって「CRITICALの脆弱性を検知したときにパイプラインを止める」といった動作ができます。

$ trivy image --exit-code 0 --severity MEDIUM,HIGH python:alpine3.13
$ trivy image --exit-code 1 --severity CRITICAL python:alpine3.13

まとめ

 今回は、Trivyについて機能を網羅的に解説しました。Trivyは当初コンテナイメージのスキャンツールというイメージがありましたが、既にイメージスキャンの領域を飛び出し、さまざまな機能を提供していることが分かります。

 今回の記事では、Trivyコマンド単独の利用方法をメインに紹介しましたが、TrivyをCI/CD(継続的インテグレーション/継続的デリバリー)パイプラインに組み込んだり、コンテナレジストリと組み合わせたりすることによって、より便利に利用できます。次回は、もう少し応用的な利用方法を紹介します。

■更新履歴

【2024/12/4】最新のv0.56.2含め2024年の情報に合うように更新しました。


Copyright © ITmedia, Inc. All Rights Reserved.

[an error occurred while processing this directive]
ページトップに戻る