とことんDevOps | 日本仮想化技術のDevOps技術情報メディア

DevOpsに関連する技術情報を幅広く提供していきます。

日本仮想化技術がお届けする「とことんDevOps」では、DevOpsに関する技術情報や、日々のDevOps業務の中での検証結果、TipsなどDevOpsのお役立ち情報をお届けします。
主なテーマ: DevOps、CI/CD、コンテナ開発、IaCなど

開催予定の勉強会

読者登録と各種SNSのフォローもよろしくお願いいたします。

VulsをDockerコンテナで動かす

インストール方法は以下に書かれているとおり、何らかのLinuxにDockerをインストールしてそれぞれコマンドを実行していくだけで動きます。 シェルスクリプトを使ったインストールでは対応するOSが動いていることが必要でしたが、この場合はLinuxであれば何でも良いようです。

vuls.io

ただ、実際動かしてみるとちょっとだけ苦労したので、ブログにまとめておこうと思いました。

脆弱性スキャンDBのダウンロード

update-all.sh を実行するように書かれていましたが、中身を見て必要なディストリビューションに絞って update-select.shとして記述しました。これを脆弱性スキャンDBのダウンロードに使います。

#!/bin/bash

./oval.sh --redhat ${@}
./oval.sh --ubuntu ${@}
./gost.sh --redhat ${@}
./gost.sh --ubuntu ${@}
./nvd.sh ${@}
./jvn.sh ${@}
./exploitdb.sh ${@}
./msfdb.sh ${@}
./kev.sh ${@}
./cti.sh ${@}

configファイルの作成

config.tomlというファイル名で用意するのですが、このあとで利用する scan.sh, report.sh, tui.sh を見る限り、シェルスクリプトファイルが置かれたディレクトリーに置く必要があるようです。

またDockerコンテナーがおそらくroot権限で処理が実行されてファイルが生成されるようで、resultsファイルとか脆弱性DBがroot権限でファイルが保存されるようです。

$ pwd
/home/ytooyama/vulsctl/docker

$ ls -lh | egrep "sqlite3|config.toml|results"
-rw-rw-r-- 1 ytooyama ytooyama  522 Aug 19 07:04 config.toml
-rw-r--r-- 1 root     root     1.5G Aug 19 05:04 cve.sqlite3
-rw-r--r-- 1 root     root      56M Aug 19 05:09 go-cti.sqlite3
-rw-r--r-- 1 root     root      65M Aug 19 05:06 go-exploitdb.sqlite3
-rw-r--r-- 1 root     root     676K Aug 19 05:37 go-kev.sqlite3
-rw-r--r-- 1 root     root     2.2M Aug 19 05:06 go-msfdb.sqlite3
-rw-r--r-- 1 root     root     280M Aug 19 05:37 gost.sqlite3
-rw-r--r-- 1 root     root     155M Aug 19 04:48 oval.sqlite3
drwx------ 4 root     root     4.0K Aug 19 06:44 results

config.tomlは次のように記述しました。対象環境にインストール済みのOSはすべてUbuntuです(MAASでデプロイしているため)。 キーパスはDockerホスト上のではなくて、-vでマウントしてコンテナーのどのパスに鍵があるかを指定します(公式ドキュメントの中ほどの図を見ると、理解できると思います)。

[default]
# if ssh config file exists in .ssh, path to ssh config file in docker
keyPath     = "/root/.ssh/id_rsa"

[servers]
  
[servers.rancher2]
host        = "172.17.28.76"
port        = "22"
user        = "ubuntu"

[servers.esxnode1]
host        = "172.17.28.51"
port        = "22"
user        = "ubuntu"

[servers.esxnode2]
host        = "172.17.28.52"
port        = "22"
user        = "ubuntu"

[servers.esxnode3]
host        = "172.17.28.53"
port        = "22"
user        = "ubuntu"

sshConfigPath = "/root/.ssh/config"の記述があるとうまく動きませんでした。 事前に、そのホストから対象の環境に対してSSHアクセスしておきます。

Vuls Scanの実行

用意されたシェルスクリプトを実行するだけです。もしくはその中身と同じようにdockerコマンドを実行します。 脆弱性DBはダウンロードしたものを使って、コンテナの中で実行されます。

実行ごとにコンテナーが実行され、結果がエクスポートされたあとコンテナーは終了されます(docker run--rmフラグを指定しているため)。

$ ./scan.sh
Using default tag: latest
latest: Pulling from vuls/vuls
Digest: sha256:d66fcbdb142d0ca18dbace6e338bfd354da2bf33b8685a2bc1345f85852f685b
Status: Image is up to date for vuls/vuls:latest
docker.io/vuls/vuls:latest
[Aug 19 07:32:23]  INFO [localhost] vuls--build-20220808_075617_1e45732
[Aug 19 07:32:23]  INFO [localhost] Validating config...
[Aug 19 07:32:23]  INFO [localhost] Detecting Server/Container OS... 
[Aug 19 07:32:23]  INFO [localhost] Detecting OS of servers... 
[Aug 19 07:32:24]  INFO [localhost] (1/4) Detected: esxnode3: ubuntu 20.04
[Aug 19 07:32:24]  INFO [localhost] (2/4) Detected: esxnode2: ubuntu 20.04
[Aug 19 07:32:24]  INFO [localhost] (3/4) Detected: esxnode1: ubuntu 20.04
[Aug 19 07:32:25]  INFO [localhost] (4/4) Detected: rancher2: ubuntu 20.04
[Aug 19 07:32:25]  INFO [localhost] Detecting OS of containers... 
[Aug 19 07:32:25]  INFO [localhost] Checking Scan Modes...
[Aug 19 07:32:25]  INFO [localhost] Checking dependencies...
[Aug 19 07:32:25]  INFO [rancher2] Dependencies... Pass
[Aug 19 07:32:25]  INFO [esxnode3] Dependencies... Pass
[Aug 19 07:32:25]  INFO [esxnode2] Dependencies... Pass
[Aug 19 07:32:25]  INFO [esxnode1] Dependencies... Pass
[Aug 19 07:32:25]  INFO [localhost] Checking sudo settings...
[Aug 19 07:32:25]  INFO [esxnode3] sudo ... No need
[Aug 19 07:32:25]  INFO [rancher2] sudo ... No need
[Aug 19 07:32:25]  INFO [esxnode2] sudo ... No need
[Aug 19 07:32:25]  INFO [esxnode1] sudo ... No need
[Aug 19 07:32:25]  INFO [localhost] It can be scanned with fast scan mode even if warn or err messages are displayed due to lack of dependent packages or sudo settings in fast-root or deep scan mode
[Aug 19 07:32:25]  INFO [localhost] Scannable servers are below...
esxnode3 rancher2 esxnode2 esxnode1 
[Aug 19 07:32:28]  INFO [localhost] vuls--build-20220808_075617_1e45732
[Aug 19 07:32:28]  INFO [localhost] Start scanning
[Aug 19 07:32:28]  INFO [localhost] config: /vuls/config.toml
[Aug 19 07:32:28]  INFO [localhost] Validating config...
[Aug 19 07:32:28]  INFO [localhost] Detecting Server/Container OS... 
[Aug 19 07:32:28]  INFO [localhost] Detecting OS of servers... 
[Aug 19 07:32:29]  INFO [localhost] (1/4) Detected: esxnode2: ubuntu 20.04
[Aug 19 07:32:29]  INFO [localhost] (2/4) Detected: esxnode3: ubuntu 20.04
[Aug 19 07:32:29]  INFO [localhost] (3/4) Detected: esxnode1: ubuntu 20.04
[Aug 19 07:32:29]  INFO [localhost] (4/4) Detected: rancher2: ubuntu 20.04
[Aug 19 07:32:29]  INFO [localhost] Detecting OS of containers... 
[Aug 19 07:32:29]  INFO [localhost] Checking Scan Modes... 
[Aug 19 07:32:29]  INFO [localhost] Detecting Platforms... 
[Aug 19 07:32:30]  INFO [localhost] (1/4) rancher2 is running on other
[Aug 19 07:32:30]  INFO [localhost] (2/4) esxnode3 is running on other
[Aug 19 07:32:30]  INFO [localhost] (3/4) esxnode2 is running on other
[Aug 19 07:32:30]  INFO [localhost] (4/4) esxnode1 is running on other
[Aug 19 07:32:30]  INFO [esxnode1] Scanning OS pkg in fast mode
[Aug 19 07:32:30]  INFO [esxnode2] Scanning OS pkg in fast mode
[Aug 19 07:32:30]  INFO [esxnode3] Scanning OS pkg in fast mode
[Aug 19 07:32:30]  INFO [rancher2] Scanning OS pkg in fast mode
[Aug 19 07:32:30]  INFO [esxnode2] Scanning listen port...
[Aug 19 07:32:30]  INFO [esxnode2] Using Port Scanner: Vuls built-in Scanner
[Aug 19 07:32:30]  INFO [rancher2] Scanning listen port...
[Aug 19 07:32:30]  INFO [rancher2] Using Port Scanner: Vuls built-in Scanner
[Aug 19 07:32:30]  INFO [esxnode3] Scanning listen port...
[Aug 19 07:32:30]  INFO [esxnode1] Scanning listen port...
[Aug 19 07:32:30]  INFO [esxnode1] Using Port Scanner: Vuls built-in Scanner
[Aug 19 07:32:30]  INFO [esxnode3] Using Port Scanner: Vuls built-in Scanner


Scan Summary
================
esxnode2    ubuntu20.04 611 installed
rancher2    ubuntu20.04 623 installed
esxnode1    ubuntu20.04 611 installed
esxnode3    ubuntu20.04 611 installed

To view the detail, vuls tui is useful.
To send a report, run vuls report -h.

Vuls Report/TUIの実行

Scanの結果の最後に書かれていますが、詳細情報はvuls tui、リポートの表示やSlackへの通知はvuls reportコマンドを実行すると可能です。

まずはVuls Reportを実行してみます。

$ ./report.sh 
Using default tag: latest
latest: Pulling from vuls/vuls
Digest: sha256:d66fcbdb142d0ca18dbace6e338bfd354da2bf33b8685a2bc1345f85852f685b
Status: Image is up to date for vuls/vuls:latest
docker.io/vuls/vuls:latest
time="Aug 19 07:48:30" level=info msg="vuls--build-20220808_075617_1e45732" 
time="Aug 19 07:48:30" level=info msg="Validating config..." 
...

そうすると、実行ごとに脆弱性スキャンを実行して環境にCVE番号が振られている脆弱性がいくつあるかチェックが実行され、ログ出力されます。

time="Aug 19 07:48:30" level=info msg="OVAL ubuntu 20.04 found. defs: 11034" 
time="Aug 19 07:48:30" level=info msg="OVAL ubuntu 20.04 is fresh. lastModified: 2022-08-19T04:48:03Z" 
time="Aug 19 07:48:30" level=warning msg="The OVAL name of the running kernel image {Release:5.4.0-124-generic Version: RebootRequired:false} is not found. So vulns of `linux` wll be detected. server: esxnode1" 
time="Aug 19 07:48:31" level=info msg="esxnode1: 145 CVEs are detected with OVAL" 
time="Aug 19 07:48:38" level=info msg="esxnode1: 1 unfixed CVEs are detected with gost" 
time="Aug 19 07:48:38" level=info msg="esxnode1: 0 CVEs are detected with CPE" 
time="Aug 19 07:48:41" level=info msg="esxnode1: 72 PoC are detected" 
time="Aug 19 07:48:41" level=info msg="esxnode1: 0 exploits are detected" 
time="Aug 19 07:48:41" level=info msg="esxnode1: Known Exploited Vulnerabilities are detected for 0 CVEs" 
time="Aug 19 07:48:51" level=info msg="esxnode1: Cyber Threat Intelligences are detected for 68 CVEs"
... 

最終的に表形式で結果が出てくるのですが、アップデート済みの環境でめちゃくちゃ脆弱性があるみたいに見えてしまいます。 以前Trivyの話題のときにも説明したとおり、OSによっては古い脆弱性情報には修正済みバージョンの情報が欠落していることがあるので、 パッチ適用済みのものが未だ存在するように見えることがあります。

そもそも、2020年4月にリリースされたUbuntu 20.04でCVE-2016-1585ガミ修正ってことはないと思うんですよね。

先程「古い脆弱性情報には修正済みバージョンの情報が欠落している」と書きましたが、これを見ると2022年以降のデータも一部欠落しているようですね。

esxnode1 (ubuntu20.04)
======================
Total: 146 (Critical:7 High:80 Medium:54 Low:5 ?:0)
0/146 Fixed, 72 poc, 0 exploits, cisa: 0, uscert: 3, jpcert: 0 alerts
611 installed

+------------------+------+--------+-----+-----------+---------+--------------------------------+
|      CVE-ID      | CVSS | ATTACK | POC |   ALERT   |  FIXED  |            PACKAGES            |
+------------------+------+--------+-----+-----------+---------+--------------------------------+
| CVE-2016-1585    |  9.8 |  AV:N  |     |           | unfixed | apparmor                       |
+------------------+------+--------+-----+-----------+---------+--------------------------------+
| CVE-2022-0318    |  9.8 |  AV:N  | POC |           | unfixed | vim                            |
+------------------+------+--------+-----+-----------+---------+--------------------------------+
| CVE-2022-1927    |  9.8 |  AV:L  | POC |           | unfixed | vim                            |
+------------------+------+--------+-----+-----------+---------+--------------------------------+
| CVE-2022-37434   |  9.8 |  AV:N  | POC |           | unfixed | zlib1g                         |
+------------------+------+--------+-----+-----------+---------+--------------------------------+
| CVE-2022-1012    |  9.1 |  AV:N  |     |           | unfixed | linux-image-5.4.0-124-generic  |
+------------------+------+--------+-----+-----------+---------+--------------------------------+
...

アップデートしてOSとして新しいパッチがない状態にしたあと、びっくりしないようにするために、 Trivyと同様に-ignore-unfixedを書き加えて実行しましょう。

docker run --rm -i \
    -v $PWD:/vuls \
    vuls/vuls report  -ignore-unfixed \
    -log-dir=/vuls/log \
    -format-list \
    -config=/vuls/config.toml \
    -refresh-cve \
    $@
    
    
esxnode1 (ubuntu20.04)
======================
Total: 0 (Critical:0 High:0 Medium:0 Low:0 ?:0)
0/0 Fixed, 0 poc, 0 exploits, cisa: 0, uscert: 0, jpcert: 0 alerts
611 installed

No CVE-IDs are found in updatable packages.
611 installed


esxnode2 (ubuntu20.04)
======================
Total: 0 (Critical:0 High:0 Medium:0 Low:0 ?:0)
0/0 Fixed, 0 poc, 0 exploits, cisa: 0, uscert: 0, jpcert: 0 alerts
611 installed

No CVE-IDs are found in updatable packages.
611 installed


esxnode3 (ubuntu20.04)
======================
Total: 0 (Critical:0 High:0 Medium:0 Low:0 ?:0)
0/0 Fixed, 0 poc, 0 exploits, cisa: 0, uscert: 0, jpcert: 0 alerts
611 installed

No CVE-IDs are found in updatable packages.
611 installed


rancher2 (ubuntu20.04)
======================
Total: 0 (Critical:0 High:0 Medium:0 Low:0 ?:0)
0/0 Fixed, 0 poc, 0 exploits, cisa: 0, uscert: 0, jpcert: 0 alerts
623 installed

No CVE-IDs are found in updatable packages.
623 installed

このオプションの動作を確認するため、config.tomlにサーバーを追加してみました。このサーバーはアップデートをせずにUbuntuをインストールしただけの状態のものです。

[servers.esxnode4]
host        = "172.17.28.54"
port        = "22"
user        = "ubuntu"

もう一度実行してみます。

$ ./scan.sh
$ docker run --rm -i \
    -v $PWD:/vuls \
    vuls/vuls report  -ignore-unfixed \
    -log-dir=/vuls/log \
    -format-list \
    -config=/vuls/config.toml \
    -refresh-cve \
    $@

そうすると、次のようにアップデートしていないサーバーは脆弱性がいくつか見つかることを確認できます。

esxnode1 (ubuntu20.04)
======================
Total: 0 (Critical:0 High:0 Medium:0 Low:0 ?:0)
0/0 Fixed, 0 poc, 0 exploits, cisa: 0, uscert: 0, jpcert: 0 alerts
611 installed

No CVE-IDs are found in updatable packages.
611 installed


esxnode2 (ubuntu20.04)
======================
Total: 0 (Critical:0 High:0 Medium:0 Low:0 ?:0)
0/0 Fixed, 0 poc, 0 exploits, cisa: 0, uscert: 0, jpcert: 0 alerts
611 installed

No CVE-IDs are found in updatable packages.
611 installed


esxnode3 (ubuntu20.04)
======================
Total: 0 (Critical:0 High:0 Medium:0 Low:0 ?:0)
0/0 Fixed, 0 poc, 0 exploits, cisa: 0, uscert: 0, jpcert: 0 alerts
611 installed

No CVE-IDs are found in updatable packages.
611 installed

esxnode4 (ubuntu20.04)
======================
Total: 4 (Critical:1 High:1 Medium:2 Low:0 ?:0)
3/4 Fixed, 2 poc, 0 exploits, cisa: 0, uscert: 0, jpcert: 0 alerts
604 installed

+----------------+------+--------+-----+-----------+---------+---------------+
|     CVE-ID     | CVSS | ATTACK | POC |   ALERT   |  FIXED  |   PACKAGES    |
+----------------+------+--------+-----+-----------+---------+---------------+
| CVE-2022-37434 |  9.8 |  AV:N  | POC |           | unfixed | rsync, zlib1g |
+----------------+------+--------+-----+-----------+---------+---------------+
| CVE-2022-2509  |  7.5 |  AV:N  |     |           |   fixed | libgnutls30   |
+----------------+------+--------+-----+-----------+---------+---------------+
| CVE-2016-3709  |  6.9 |  AV:N  | POC |           |   fixed | libxml2       |
+----------------+------+--------+-----+-----------+---------+---------------+
| CVE-2021-4209  |  6.5 |  AV:N  |     |           |   fixed | libgnutls30   |
+----------------+------+--------+-----+-----------+---------+---------------+


rancher2 (ubuntu20.04)
======================
Total: 0 (Critical:0 High:0 Medium:0 Low:0 ?:0)
0/0 Fixed, 0 poc, 0 exploits, cisa: 0, uscert: 0, jpcert: 0 alerts
623 installed

No CVE-IDs are found in updatable packages.
623 installed

ただこれもCVE-2016-3709はすでに修正されているような?

同様に、tui.shの方も同じフラグを設定することで、同じような対応が可能です。

$ docker run --rm -it\
    -v $PWD:/vuls \
    vuls/vuls tui -ignore-unfixed $@ \
    -log-dir=/vuls/log \
    -config=/vuls/config.toml\
    -refresh-cve \
    $@

次のように表示されます。アップデート適用済みのノードでは脆弱性なしと表示され、アップデートされていない環境は脆弱性が表示されます。

アップデート済みのノードをスキャンした結果

アップデート未適用の環境のスキャン結果

ただしこのフラグ(-ignore-unfixed)はunfixedな脆弱性を非表示にするオプションなので、本当に当てられていない脆弱性までフィルタリングされてしまう可能性があります。基本的にはCVE番号が振られた脆弱性がリストされた場合は早急に対応するようにするのが重要です。

最初はフラグを使わずに実行して、パッチを当てたあとのスキャンでフラグを付けて実行すると良いと思われます。

ちょっと一部疑問点が残る部分はありましたが、DockerコンテナーでVulsを実行してノードの脆弱性スキャンができる環境をセットアップできました。 リストアップされた脆弱性については、一つ一つ潰していこうと思います(ちなみに、RHELやRHELクローンのOS、Alpine Linuxベースについては良い感じで動いてくれました)。

最後に、ヘルプを見るときはこんな感じで実行すれば良い感じです。ネイティブにインストールするときとCLIの使い方はそんなに変わりませんね。

$ docker run --rm -i -v $PWD:/vuls vuls/vuls --help
Usage: vuls <flags> <subcommand> <subcommand args>

Subcommands:
    commands         list all command names
    flags            describe all known top-level flags
    help             describe subcommands and their syntax

Subcommands for configtest:
    configtest       Test configuration

Subcommands for discover:
    discover         Host discovery in the CIDR

Subcommands for history:
    history          List history of scanning.

Subcommands for report:
    report           Reporting

Subcommands for scan:
    scan             Scan vulnerabilities

Subcommands for server:
    server           Server

Subcommands for tui:
    tui              Run Tui view to analyze vulnerabilities


Use "vuls flags" for a list of top-level flags

CI/CDパイプラインへの組み込み

VulsではホストのOS脆弱性を、コンテナイメージのスキャンはTrivyでチェックをして、そのキャッシュを-trivy-cachedb-dirで指定して実行すると、ホストとコンテナ関係の脆弱性を収集して、Slackやメールなどで投げられそうです。引き続き調査していきます。