管理下の各サーバがどのような脆弱性を内包しているか、サーバ管理者は最新の情報に照らして適時調査して把握しておく必要がある。この調査を簡単に行うためのOSS (オープンソースソフトウェア) な脆弱性検知ツールとして、対象サーバ側にエージェントが不要という「Vuls」を試してみることにした。VulsはIPAのIPAテクニカルウォッチ「脆弱性対策の効果的な進め方(ツール活用編)」に取り上げられてもいる。
本記事でのVulsのインストールは、Vuls公式サイト Vuls · Agentless Vulnerability Scanner for Linux/FreeBSD にある次のドキュメントに沿って進める。
Vulsを動作させる実験用のホストとして次のようなスペックの仮想マシンを用意し、Ubuntu Server 22.04 LTSをインストールする。
項目 | 内容 | 備考 |
---|---|---|
OS | Ubuntu Server 22.04 LTS | |
CPU | x86_64 (amd64), 8core | aarch64 (arm64) 環境でも動作OKでした |
メモリ | 4GB | たとえば2GBでは不足でswapが発生、データベース処理が苦しそう |
ストレージ | 32GB | DBファイル (sqlite3) のサイズが数GBに達する模様 |
ユーザ名 | TESTUSER |
ホストではDockerが動作している必要がある。Dockerの環境構築で楽するためにスクリプトでインストールする。
$ curl -fsSL https://get.docker.com -o get-docker.sh
$ sudo sh ./get-docker.sh --dry-run
# Executing docker install script, commit: a8a6b338bdfedd7ddefb96fe3e7fe7d4036d945a
apt-get update -qq >/dev/null
DEBIAN_FRONTEND=noninteractive apt-get install -y -qq apt-transport-https ca-certificates curl >/dev/null
mkdir -p /etc/apt/keyrings && chmod -R 0755 /etc/apt/keyrings
curl -fsSL "https://download.docker.com/linux/ubuntu/gpg" | gpg --dearmor --yes -o /etc/apt/keyrings/docker.gpg
chmod a+r /etc/apt/keyrings/docker.gpg
echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu jammy stable" > /etc/apt/sources.list.d/docker.list
apt-get update -qq >/dev/null
DEBIAN_FRONTEND=noninteractive apt-get install -y -qq docker-ce docker-ce-cli containerd.io docker-compose-plugin docker-ce-rootless-extras docker-buildx-plugin >/dev/null
$ time sudo sh ./get-docker.sh
(snip)
To run Docker as a non-privileged user, consider setting up the
Docker daemon in rootless mode for your user:
dockerd-rootless-setuptool.sh install
Visit https://docs.docker.com/go/rootless/ to learn about rootless mode.
(snip)
real 0m27.630s
user 0m0.002s
sys 0m0.007s
Dockerはrootless modeで使ってみる。指示に沿ってDockerのインストールを進めると、今回の環境の場合はuidmap
パッケージが必要とわかったので併せてインストールする。
$ dockerd-rootless-setuptool.sh install
[ERROR] Missing system requirements. Run the following commands to
[ERROR] install the requirements and run this tool again.
########## BEGIN ##########
sudo sh -eux <<EOF
# Install newuidmap & newgidmap binaries
apt-get install -y uidmap
EOF
########## END ##########
$ sudo apt-get install -y uidmap
$ dockerd-rootless-setuptool.sh install
(snip)
[INFO] Installed docker.service successfully.
[INFO] To control docker.service, run: `systemctl --user (start|stop|restart) docker.service`
[INFO] To run docker.service on system startup, run: `sudo loginctl enable-linger TESTUSER`
[INFO] Creating CLI context "rootless"
Successfully created context "rootless"
[INFO] Use CLI context "rootless"
Current context is now "rootless"
[INFO] Make sure the following environment variables are set (or add them to ~/.bashrc):
export PATH=/usr/bin:$PATH
Some applications may require the following environment variable too:
export DOCKER_HOST=unix:///run/user/1000/docker.sock
上記の出力結果 (の趣旨) を確認し、必要な環境変数を~/.bashrc
に追記しておく。
$ diff ~/.bashrc.original ~/.bashrc
117a118,120
>
> # CUSTOM
> export DOCKER_HOST=unix:///run/user/$(id -u)/docker.sock
ユーザの実行権限でDockerが起動していることを確認する。
$ systemctl --user status docker.service
● docker.service - Docker Application Container Engine (Rootless)
Loaded: loaded (/home/TESTUSER/.config/systemd/user/docker.service; enabled; vendor preset: enabled)
Active: active (running) since Fri 2023-04-07 14:33:37 UTC; 4min 21s ago
(snip)
システム起動時にrootless modeのDockerを起動させるためには、次のコマンドを実行する。
$ sudo loginctl enable-linger TESTUSER
「Easy setup tool for Vuls」であるvulsctlをGitHubからクローンする。
$ git clone https://github.com/vulsio/vulsctl.git
$ cd vulsctl
クローンしたリポジトリ内のdockerディレクトリに移動して、update-all.sh
を実行する。脆弱性データベースの取得完了までは数十分の時間がかかる。
$ cd docker
$ time ./update-all.sh
(snip)
real 22m27.931s
user 0m3.153s
sys 0m2.466s
スキャンの対象サーバを定義するファイルとして、リポジトリ内のdockerディレクトリにconfig.toml
を作成する。対象サーバはファイル内に複数記述することができる。リモートの対象サーバに対しては公開鍵認証を使ったSSHログインが行われるので、その際にyes/noのキー入力を要求されないように、事前にSSHログインを手動で行っておく (=ホストの~/.ssh/known_hosts
に対象サーバを登録しておく)。
$ cat config.toml
[default]
user = "TESTUSER"
port = "22"
keyPath = "/root/.ssh/id_ed25519"
scanMode = ["fast"]
[servers]
## localhostをスキャンする例
[servers.localhost]
host = "127.0.0.1"
port = "local"
## リモートサーバをスキャンする例
[servers.server1]
host = "server1.example.com"
port = "1234"
[servers.server2]
host = "server2.example.com"
脆弱性スキャンを実施する前に、configの内容をテストする。ちなみに上記の「known_hostsへの登録」を行っていないサーバがスキャン対象にある場合、本テストの段階でエラーが発生してくれるので対応する。
## vuls configtest の代わりとして
$ ./config-test.sh
次の3つのコマンドを実行すると、脆弱性スキャンが実施されてresults
ディレクトリにスキャン結果が保存され、レポートが確認できるTUI (Terminal-based User Interface) が表示される。
$ ./scan.sh
$ ./report.sh
$ ./tui.sh
Web UIでレポートを確認する場合は、tui.sh
の代わりにvulsrepo.sh
を実行する。
$ ./vulsrepo.sh
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
04f95db27414 ishidaco/vulsrepo "vulsrepo-server" 6 minutes ago Up 6 minutes 0.0.0.0:5111->5111/tcp, :::5111->5111/tcp suspicious_almeida
その後にhttp://DockerホストのIPアドレス:5111/
へウェブブラウザでアクセスすると、Vulsのレポートを表や棒グラフの形で見ることができる。ちなみにVulsRepoのオンラインデモが https://monocosel.jp/vulsrepo/ で公開されているので、事前に実際の操作感を確認できる。
公式ドキュメントの次の2つを参照すると、
ずばり私がやりたい、「定期的に、“CVSSスコアが7.0以上 (深刻度が重要以上) のCVEに関してのみ、かつ、unfixed (未修正) なものは除外した内容”をSlack通知する」仕組みを実現するためには、まずはSlack https://api.slack.com/ からIncoming WebHooksを使うAppを新規追加して (参考ページ)、config.toml
に次のようなWebhook設定を追加し、
## config.tomlへの追加分
[slack]
hookURL = "https://hooks.slack.com/services/XXXXXXXXX/XXXXXXXXXXX/XXXXXXXXXXXXXXXXXXXXXXXX"
channel = "#alert_vuls"
authUser = "vulsrepo"
さらに次の3つのコマンドを定期的にcronで実施すれば良い。
$ ./update-all.sh
$ ./scan.sh
$ ./report.sh -cvss-over=7.0 -ignore-unfixed -to-slack
サーバに対する脆弱性スキャンを専用エージェントなしで、サーバ台数に関わらず一箇所から行えるVuls + Vulsctlというツールは、「なぜ今まで手元になかったのか」と逆に言いたくなるくらい必須の存在になりうると感じている。スケーラブルだし、良いものですね。(そしてもちろん、脆弱性対応はパッチを当てる運用までが大切!)