脆弱性診断ツールVulsをDockerで運用する

# 背景
サーバーOSに各Linuxディストリビューションを導入した時、今日では各クラウド用イメージから、またはISOファイルから手動インストールします。
構築した際にはインストールした各パッケージのライブラリなどは最新版ですが、時間の経過と共に新たな脆弱性が発見されて修正パッチがリリースされます。
昨今、脆弱性を悪用したサイバー攻撃は修正パッチがリリースされてから時間をあまり置かず世界中から同時多発的で開始される状況です。
管理者としては重大な脆弱性に対する修正パッチがリリースされたら迅速に対応したい所です。
しかしインストールしたパッケージ数に比例して確認する脆弱性も増えます。また確認すべき脆弱性を見逃す事も考えられます。
さらに管理するサーバーの台数が増えれば、もう迅速に対応するには人力では限界があります。
そこでLinuxディストリビューションの各パッケージの脆弱性を自動で検知する仕組みを実現しているVulsを利用します。
なおVulsはラズパイ(Raspberry Pi)OSのRaspbianやAWSのAmazon LinuxやLinux以外にFreeBSDにも対応しています。

- [Vuls: Agentless Vulnerability Scanner for Linux/FreeBSD](https://vuls.io/)

詳細については公式サイトで分かりやすく掲載されていますので参照して下さい。

# VulsをDockerベースで構築
cronで定期的に各サーバーを脆弱性診断する運用では、専用にサーバーを用意して手動インストール方法が妥当かと思います。
ノートPCに入れてスポットで運用する場合などはVMに手動インストールでも良いのですが、Dockerのコンテナでササッと用意出来たらいいですね。
Vulsには公式のDockerイメージも用意されていますので導入は簡単です。

- [Vuls-Docker](https://hub.docker.com/r/vuls/vuls/)

詳細については公式サイトで分かりやすく掲載されていますので参照して下さい。

## Docker環境の準備

以下のページにて紹介していますので参考にしてみて下さい。

- [Linuxサーバー環境のDockerインストールメモ - Qiita ](https://qiita.com/ohhara_shiojiri/items/486a54ad895d6bb3144e)


## Vulsctlのインストール
Vulsの環境設定に以前は複数のスクリプトファイルを作成していましたが、今日では公式から簡単に一括で設定できるツールVulsctlが用意されています。

- [Vulsctl](https://vuls.io/docs/ja/install-with-vulsctl.html)

こちらを使うと簡単に一括設定出来ます。

### 1.Vulsctlをgitクローンする

```
$ git clone https://github.com/vulsio/vulsctl.git
```
### 2.脆弱性データベースの更新
Vulsで使用される各脆弱性データベースのDocker Imageをdocker pullして最新版に更新し、脆弱性データベースのsqlite3ファイルを作成して最新データに更新します。

```
$ cd vulsctl/docker
$ ./update-all.sh
```

### 3.vulsの設定ファイル
vulsの設定ファイル(config.toml)は脆弱性診断の対象サーバーに対する接続情報などを記載します。

```config.toml
[default]
port = "22"
user = "ユーザーアカウント名"
sshConfigPath = "/root/.ssh/config" # ホストがDebian or Ubuntuでは必須
keyPath = "/root/.ssh/id_rsa"
scanMode = ["fast"]

[servers]

[servers.remote-server]
host = "リモートIPアドレス or ホスト名"
user = "ユーザーアカウント名"
containerType = "docker"
containersIncluded = ["${running}"]
```

リモートホストに接続する際の秘密鍵のパス(keyPath)は「/root/.ssh/」以下である事がDockerコンテナの場合は必要です。
これは透過的に利用されますので実体はローカルホストのユーザーアカウント側になります。

## 設定ファイルチェックと脆弱性スキャンの実行
config.tomlファイルの内容に誤りがないかチェックして脆弱性のスキャンを実行します。

```
$ ./scan.sh
```

## 脆弱性診断レポート
脆弱性診断が完了したら診断結果レポートをコマンドライン表示出来ます。

```
$ ./report.sh
```

## Vulsの脆弱性診断レポート(TUI)
診断結果レポートをTUI画面表示も出来ます。

```
$ ./tui.sh
```

## Vulsの脆弱性診断レポート(GUI)
web画面に診断結果を表示するVulsrepoもコンテナがありますので、簡単にGUI表示出来ます。

- [VulsRepo](https://vuls.io/docs/ja/vulsrepo.html)

```
$ ./vulsrepo.sh
```

webブラウザで5111ポートを指定すれば表示出来ます。
http://[localhost]:5111

## サーバー環境での定期実行

常時稼働しているサーバーの脆弱性診断は毎回定期的にcronで実施した方が良いでしょう。
その為には各脆弱性データベースを最新に更新した後でvuls scanを実行します。
その後にはレポートを作成します。また古いレポートが貯まらないように削除して掃除しましょう。

### 脆弱性データベースの定期更新
初回のデータベース更新は「update-all.sh」で1度行っていますので同様に定期的に実行すれば良いのですが各データベース更新がデータの取得に時間が掛かります。「go-cve-dictionary」のnvdとjvnについては年毎に差分だけで済むようにスクリプトを修正してみます。

元ファイルから適当にコピーします。
```
$ cp update-all.sh update-all-year.sh
```

現在の年だけで差分更新するように修正
```:update-all-year.sh
YEAR="$(date "+%Y")"

./nvd-cron.sh $YEAR     
./jvn-cron.sh $YEAR
```

cronで定期実行する様に設定
```
$ crontab -l
00 1 * * * cd /home/[ユーザー名]/vulsctl/docker ; ./update-all-year.sh > /tmp/update-all-year.log 2>&1
```

### vuls scanの定期実行

脆弱性スキャンを実施する際にコンテナを有効化しているとvulsコンテナ自体もスキャンされますがコンテナ名が毎回変わってしまうのでvulsと固定設定します。
また日時とタイムゾーンをホスト側に合わせるように編集します。

```:scan.sh
docker run --rm \
    --name vuls \ # コンテナ名を設定
    -v $HOME/.ssh:/root/.ssh:ro \
    -v $PWD:/vuls \
    -v /etc/localtime:/etc/localtime:ro -v /etc/timezone:/etc/timezone:ro \ # 日時とタイムゾーンをホスト側に合わせる
    vuls/vuls scan \
    -log-dir=/vuls/log \
    -config=/vuls/config.toml \
    $@
```

cronで定期実行する様に設定
```
$ crontab -l
00 2 * * * cd /home/[ユーザー名]/vulsctl/docker ; ./scan.sh > /tmp/scan.log 2>&1
```

### レポート作成の定期実行

vuls scanした後のレポート作成をcronで定期実行する様に設定
```
$ crontab -l
00 3 * * * cd /home/[ユーザー名]/vulsctl/docker ; ./report.sh > /tmp/vuls_report.log 2>&1
```

### ログの定期削除
定期実行しているとログデータが段々増えていきますので、一定期間より古いデータを削除する様にします。
Dockerコンテナがroot権限実行によりパーミッション制限がありますので、Vulsrepoコンテナ経由で削除する事にします。
vulsctlのスクリプトではvulsrepoコンテナに名前が設定されていないので修正しします。

```:vulsrepo.sh
#!/bin/bash

docker pull ishidaco/vulsrepo

docker run -dt \
    --name vulsrepo \ # コンテナ名を設定
    -v $PWD:/vuls \
    -p 5111:5111 \
    ishidaco/vulsrepo \
    $@
```

vulsrepoコンテナ経由で7日以前より古いログを削除するスクリプトファイルを新規用意します。

```:vulsrepo-log-clear.sh
#!/bin/bash

/usr/bin/docker exec vulsrepo find /vuls/results -mtime +7 -exec /bin/rm -rf {} \;
```

この場合は、7日より古いログが削除されます。
ファイルに実行属性を付与します。

```
$ chmod +x vulsrepo-log-clear.sh
```

cronで定期実行する様に設定
```
$ crontab -l
00 4 * * * cd /home/[ユーザー名]/vulsctl/docker ; ./vulsrepo-log-clear.sh > /tmp/vulsrepo-log-clear.log 2>&1
```


# 勉強会での実演方法(過去ログ)
Vulsの動作を勉強会で実演する為に用意した機材は以下の通り。

- VulsをDockerベースで構築したノートPC(OS:Linux Mint)
- 脆弱性診断対象：ラズパイ(Raspberry Pi 2)OS Raspbian-wheezy
- 有線LAN接続環境

脆弱性診断対象のラズパイは意図して古いバージョンのRaspbianを用意してパッケージ更新をしない状態で用意しました。
予め脆弱性データベースの更新を済ませて実演時間を調整しておく。

勉強会告知：[OSS活用勉強会 第八回 勉強会 オープンソースで始めるLinuxサーバーの脆弱性診断入門]
(https://atnd.org/events/90079)
勉強会告知：[OSS活用勉強会 第八回 勉強会 オープンソースで始めるLinuxサーバーの脆弱性診断入門]
(https://connpass.com/event/65621/)
スライド資料：[オープンソースで始めるLinuxサーバー脆弱性診断入門]
(https://www.slideshare.net/ShinichiroOhhara/linux-79365978)