脆弱性スキャンツールGrypeの使い方

grypeは脆弱性検知ツールの一つであり，SBOMをスキャンすることで各ソフトウェアがどのような脆弱性に脅かされているかを検知できます。また，grypeの開発元はsyftと同じであり，syftと連携することを考え作られています。
[grype公式ドキュメント](https://github.com/anchore/grype)には、grypeの様々な機能詳細や仕様、環境変数の設定について記述されています。この記事では、自分が使う上で、使用頻度の高い機能について、紹介します。

**検証環境**
- Ubuntu 22.04.3 LTS (WSL2)

| コンポーネント | バージョン | 使用用途                 | 
| -------------- | ---------- | ------------------------ | 
| Docker         | 24.0.5     | コンテナイメージのビルド | 
| syft           | v0.91.0    | SBOM生成ツール           | 
| grype          | v0.69.0    | 脆弱性検知               | 

- [install方法](#install方法)
    - [0. 解凍用の一時的なファイルの作成](#0-解凍用の一時的なファイルの作成)
    - [1. grypeのバイナリファイルの取得](#1-grypeのバイナリファイルの取得)
    - [2. grypeのバイナリファイルの解凍](#2-grypeのバイナリファイルの解凍)
    - [3. grypeのpathを通す](#3-grypeのpathを通す)
- [grype DB (データベース)](#grype-db-データベース)
    - [1. DBリスト取得](#1-dbリスト取得)
    - [2. grype DBの設置](#2-grype-dbの設置)
    - [3. grype DBのバージョン確認](#3-grype-dbのバージョン確認)
  - [grype DB管理用のコマンド](#grype-db管理用のコマンド)
  - [grype DBの注意点](#grype-dbの注意点)
- [grypeでSBOMをスキャンしてみる](#grypeでsbomをスキャンしてみる)


# install方法
まず、grypeを使うためにそのインストール方法について説明します。インストール方法はsyftの場合とほぼ同じです。
### 0. 解凍用の一時的なファイルの作成
まず、grypeを解凍するための一時的なディレクトリを作成し、そのディレクトリへ移動します：
```bash
$ mkdir /tmp/grype/ && cd /tmp/grype/
```


### 1. grypeのバイナリファイルの取得
grypeの[リリース情報](https://github.com/anchore/grype/releases)から、アーカイブファイルを取得します。
今回は、[grype-v0.69.0](https://github.com/anchore/grype/releases/download/v0.69.0/grype_0.69.0_linux_amd64.tar.gz)から、バージョン0.69.0のgrypeのアーカイブである`grype_0.69.0_linux_amd64.tar.gz`を取得します：
```bash
$ wget https://github.com/anchore/grype/releases/download/v0.69.0/grype_0.69.0_linux_amd64.tar.gz
```

### 2. grypeのバイナリファイルの解凍
そして、解凍行います：
```bash
$ tar xvf grype_0.69.0_linux_amd64.tar.gz
```
解凍後、以下のように結果が出力されます：
```bash
CHANGELOG.md
LICENSE
README.md
grype
```

### 3. grypeのpathを通す
最後にgrypeを実行するために適切な場所へgrypeバイナリを移動します：
```bash
$ sudo mv grype /usr/local/bin
```
今回は、`/usr/local/bin`へgrypeを配置しました。
一時的なディレクトリ`/tmp/grype`は必要ないので削除してしまってもよいです：
```bash
$ cd ~
$ rm -rf /tmp/grype/
```

grypeの場所とバージョンを確認し、以下のように出力されていれば、grypeのインストールは成功です：
```bash
$ grype version
Application:         grype
Version:             0.69.0
BuildDate:           2023-09-20T20:56:04Z
GitCommit:           da3de94842f51059f32409289d863792726f83ba
GitDescription:      v0.69.0
Platform:            linux/amd64
GoVersion:           go1.21.1
Compiler:            gc
Syft Version:        v0.91.0
Supported DB Schema: 5
```

```bash
$ which grype
/usr/local/bin/grype
```

# grype DB (データベース)
grypeは専用の脆弱性データベースを用いて、脆弱性のスキャンを行います。ここでは、grypeでスキャンをする前に、grype DBの使い方を説明します。grypeをインストール後、自分のローカル環境にgrype DBを配置する必要があります。`grype db`コマンドを用いてgrypeデータベースに関する操作を行うことができます。

### 1. DBリスト取得
まず、以下のコマンドで、grype DBのリストを取得します：
```bash
grype db list
```
このとき、以下のようにgrype DBの一覧が取得できます
```
Built:    2023-10-06 01:24:11 +0000 UTC
URL:      https://toolbox-data.anchore.io/grype/databases/vulnerability-db_v5_2023-10-06T01:24:11Z_3efb2852b6383a7809d2.tar.gz
Checksum: sha256:c38ff0785a05c528d2038333c397f4a1e2164bc0ebe5f429484110ffc9e5a980

Built:    2023-10-05 01:24:28 +0000 UTC
URL:      https://toolbox-data.anchore.io/grype/databases/vulnerability-db_v5_2023-10-05T01:24:28Z_17b232c51ce3734f92f5.tar.gz
Checksum: sha256:d842e5fd5c1f2ca0a0864e8a98698727ca6b0fb49928cc55ec14f752bfaeda68

Built:    2023-10-04 01:25:27 +0000 UTC
URL:      https://toolbox-data.anchore.io/grype/databases/vulnerability-db_v5_2023-10-04T01:25:27Z_22681858d0461218ab2a.tar.gz
Checksum: sha256:86afbdc332df0360e9775d71b97a75a0510dfe13529111abd9e206df1088034c
.............
.............
```
grypeのデータベースは毎日更新されています。

### 2. grype DBの設置
リストを取得後、以下のコマンドを用いて最新のデータベースを取得し、配置します：
```bash
$ wget https://toolbox-data.anchore.io/grype/databases/vulnerability-db_v5_2023-10-06T01:24:11Z_3efb2852b6383a7809d2.tar.gz

$ grpye db import <脆弱性DBのtar.gz>
Vulnerability database imported
```
自分の場合、脆弱性DBのtar.gzは`vulnerability-db_v5_2023-10-06T01:24:11Z_3efb2852b6383a7809d2.tar.gz`でした。

これで、ローカル上にgrype DBを設置することができました。DBの場所はユーザーのディレクトリ`home/usr名`の`.cache/grype`というディレクトリに存在しています。

### 3. grype DBのバージョン確認
以下のコマンドを実行すると、現在使用しているgrype DBの情報を見ることができます：
```bash
$ grype db status
Location:  /home/usr名/.cache/grype/db/5
Built:     2023-10-06 01:24:11 +0000 UTC
Schema:    5
Checksum:  sha256:bf2bcf8cedf4230cb37bf1e3a322a1d251a51683829968bd7554ff8e81995930
Status:    valid
```
## grype DB管理用のコマンド
gryoe DBを管理するためのコマンドをここでまとめておきます
`grype db status` : 現在のgrype DBの状態を確認できる。DBの場所、ビルドされた日付、checksumを確認できる。

`grype db check`  DBに対して、アップデートが可能かどうかを見ることができます。

`grype db update` : 最新のlatestのDBが`.cache`ディレクトリへダウンロードされる。デフォルトでgrypeではスキ—ャンするたびに最新のDBにアップデートされる。

`grype db list` : ダウンロード可能なDB、そのURLを確認することができる。

`grype db import` : grype DBのアーカイブを使って、DBをダウンロードできる。

`grype db --help` : コマンドに関する情報を確認することができる。

## grype DBの注意点
grype DBは毎日最新のDBに更新されており、正確な脆弱性状を手に入れるために、grypeスキャン時に最新のDBにアップデートしていく必要があります。また、ローカルのDBが過去5日以内にbuildされていない場合、grypeのスキャン実行に失敗するため注意が必要です。
<!-- Grypeが正確なマッチを提供するためには、最新の脆弱性情報が必要です。デフォルトでは、ローカルデータベースが過去5日以内に構築されていない場合、実行に失敗します。データの陳腐化チェックは環境変数`GRYPE_DB_MAX_ALLOWED_BUILT_AGE` と `GRYPE_DB_VALIDATE_AGE` 、または `db` 配下のフィールド `max-allowed-built-age` と `validate-age` で設定できます。golang's time duration syntax](https:／／pkg.go.dev／time＃ParseDuration)を使う。GRYPE_DB_VALIDATE_AGE`または`validate-age`に`false`を設定すると、stalenessチェックが無効になる。  -->

# grypeでSBOMをスキャンしてみる
チュートリアルとして、SBOM生成ツール**syft**で生成したSBOMをスキャンし、脆弱性データを見ていきます。前回の記事[SBOM生成ツールSyftの使い方](https://qiita.com/keimatsumo/items/21a797029568594cb223)で作成したディレクトリ`syft-test`へ移動してください。そこに前回作成したSBOM `syft-python.json`があるはずです。そのSBOMに対して、以下のコマンドを実行することでスキャンできます：
<!-- ```bash
grype sbom:./${SBOM_FILE}.json -o table=${SCAN_DIR}${SCAN_DIR_CURRE}${GRYPE_FILE}.txt
``` -->
```bash
$ grype sbom:./syft-python.json -o table=scan.txt
 ✔ Vulnerability DB                [no update available]
 ✔ Scanned for vulnerabilities     [791 vulnerability matches]
   ├── by severity: 3 critical, 60 high, 227 medium, 30 low, 453 negligible (18 unknown)
   └── by status:   21 fixed, 770 not-fixed, 0 ignored
```
grype DBから791件の一致する脆弱性が発見されたことがわかります。
スキャン結果`scan.txt`を見てみると、以下のようになっています。今回は抜粋して掲載します：
```bash
NAME                          INSTALLED                FIXED-IN           TYPE    VULNERABILITY     SEVERITY   
apt                           2.6.1                                       deb     CVE-2011-3374     Negligible
libc-bin                      2.36-9+deb12u1           2.36-9+deb12u3     deb     CVE-2023-4911     High      
libwmf-dev                    0.2.12-5.1                                  deb     CVE-2007-3476     Low       
linux-libc-dev                6.1.52-1                                    deb     CVE-2023-25775    Critical    
python3.11                    3.11.2-6                                    deb     CVE-2023-40217    Medium      
...........
...........
...........
```
ここで、スキャン結果の注目すべき特徴について説明します。まず、スキャンテーブルのヘッダーの項目はそれぞれ以下を表しています：
- NAME : パッケージの名前
- INSTALLED : インストールされているパッケージのバージョン
- FIXED-IN : ソフトウェアの脆弱性が修正され、セキュリティパッチが適用されたバージョン
- TYPE : パッケージのタイプ
- VULNERABILITY : 脆弱性に対してつけられた識別子が出力される。今回のスキャンでは、CVE識別番号と呼ばれる識別子がつけられている。
- SEVERITY : Critical, High, Medium, Low, Negligibleのレベルで分類されており、HighやCriticalと判定されたパッケージに対しては、その脆弱性を調べ、対策することを推奨されている。

重要な`FIXED-IN`について、詳しく説明します。日本語では「修正された」という意味です。「修正された」とは、ソフトウェアの脆弱性が修正され、セキュリティパッチが適用されたことを意味します。つまり、脆弱性に対するセキュリティアップデートが提供されており、FIXED-INでは、そのアップデートが適用されたバージョンが存在しており、そのバージョンについて記述されています。
例えば、今回の例を見てみましょう：
```
NAME                          INSTALLED                FIXED-IN           TYPE    VULNERABILITY     SEVERITY   
libc-bin                      2.36-9+deb12u1           2.36-9+deb12u3     deb     CVE-2023-4911     High
```
ここでは、libc-binというパッケージのバージョン 2.36-9+deb12u1 に対して、脆弱性が検知されています。そして、バージョン 2.36-9+deb12u1 に存在した CVE-2023-4911という脆弱性が、バージョン 2.36-9+deb12u3 で修正され、セキュリティの問題が解決されたことを意味しています。

したがって、すでに修正された脆弱性については、ユーザーが`FIXED-IN`を見て、そこに記述されたバージョンをインストールすることで、脆弱性によるセキュリティの問題を解決することができる。一方、`FIXED-IN`項目が空欄になっている、すなわち、「修正されていない」脆弱性は、セキュリティアップデートがまだ提供されておらず、脆弱性が依然として存在する状態を指しています。

脆弱性が修正されたパッケージのみを出力したい場合は、`grype`のコマンドにフラグ`--only-fixed`を使えばよく、一方、脆弱性が修正されていないパッケージのみを出力したい場合は`--only-notfixed`フラグを使います。

実行例でも見たようにgrypeによるスキャンは、大量の脆弱性を検知します。そのため、`FIXED-IN`項目や脆弱性のレベルを観測し、重要なものだけ抽出することで確認すべき脆弱性の数を減らせることができ、これらがgrypeの運用において重要になります。