AL@のTech Blog

個人用備忘録

【Vuls】Linuxサーバの脆弱性を検知してみた part1 (Vulsの構築)

管理していたLinuxサーバが知らぬ間に脆弱性の危機に・・・
何てことがないように脆弱性を検知してくれる仕組みがあると便利ですよね。
ってことでVulsを構築してみました。


リモートのクライアントサーバを検知させる場合、パッケージ情報を送信する方法としてSSHを使ったリモートスキャンモードがあります。
ただ、今回はSSHを使わないサーバモードにします。
こちらだと鍵自体が不要かつ、指定した任意のportさえ通信を許可すればパッケージ情報を送信できるので非常にシンプルでよいですね。

目次

 1. 前提
 2. Vulsサーバ側の事前準備
 3. Goインストール
 4. go-cve-dictionaryのインストール
 5. goval-dictionaryのインストール
 6. Vulsのインストール
 7. vulsrepoのインストール
 8. Vuls,vulsrepoをsystemd化する
 9. 脆弱性検知&確認

1. 前提

【Vulsサーバ側】
サーバ名:vuls-server
EC2インスタンスタイプ:t2.medium
EBSボリューム:16GB
OS:Amazon Linux 2
DB:Sqlite3
Go:ver1.21.1
※後ほどの手順にも記載しますが、インストール途中でプロセスがkillされてしまう、またデフォルトのEBSボリュームだと足りなかったため、Vulsサーバ側だけ少しスペック上げてます。


【Vulsクライアント側】
サーバ名:vuls-client
OS:Amazon Linux 2
EC2インスタンスタイプ:t2.micro
EBSボリューム:8GB

また、Vuls関連のインストール手順は公式ドキュメントを参考に進めていきます。
vuls.io



2. Vulsサーバ側の事前準備

基本設定や必要パッケージをインストールしていきます。
ちなみにVulsクライアント側は脆弱性検知をさせたいので敢えてアップデートせずにそのままにしておきます。

getenforce
>Disabled

timedatectl set-timezone Asia/Tokyo

yum -y update
yum -y install git gcc make wget vim

 
 

3. Goインストール

vulsはgoで作られているみたいなので、Goをインストールします。
最新版のGoをインストールする場合は、公式サイトで都度確認してください。
go.dev

cd /opt
wget https://go.dev/dl/go1.21.1.linux-amd64.tar.gz
tar -C /usr/local -xzf go1.21.1.linux-amd64.tar.gz
rm -rf go1.21.1.linux-amd64.tar.gz

 

環境変数の設定をします。

vim /etc/profile.d/goenv.sh

export GOROOT=/usr/local/go
export GOPATH=/opt/go
export PATH=$PATH:$GOROOT/bin:$GOPATH/bin

source /etc/profile.d/goenv.sh

 
 

4. go-cve-dictionaryのインストール

脆弱性データベースのインストール作業となります。
インストールする脆弱性データべースは、アメリカのNISTが管理しているNVD(National Vulnerability Database)と日本のJPCERT/CCIPAが共同で管理しているJVN(Japan Vulnerability Notes)となります。

mkdir /var/log/vuls
chmod 700 /var/log/vuls
mkdir -p $GOPATH/src/github.com/vulsio
cd $GOPATH/src/github.com/vulsio

git clone https://github.com/vulsio/go-cve-dictionary.git
cd go-cve-dictionary
make install
mkdir /opt/vuls
cd /opt/vuls
go-cve-dictionary fetch jvn
go-cve-dictionary fetch nvd

前提にも記載しましたが、t2.microのEC2インスタンス上でgo-cve-dictionary fetch nvdを実行すると急にkillされてしまいましたので、個人的にはt2.micro以上のスペックで実行することをオススメします。
 
 

5. goval-dictionaryのインストール

OVAL(Open Vulnerability and Assessment Language)情報を取得するためのツールです。詳細は下記サイト参考にいただければ。
www.ipa.go.jp
 
 

mkdir -p $GOPATH/src/github.com/vulsio
cd $GOPATH/src/github.com/vulsio
git clone https://github.com/vulsio/goval-dictionary.git
cd goval-dictionary
make install
ln -s $GOPATH/src/github.com/vulsio/goval-dictionary/oval.sqlite3 /opt/vuls/oval.sqlite3

 
今回は検知対象のサーバがAmaozon Linux 2ですが、念のためすべて入れておきました。
GitHub - vulsio/goval-dictionary: Build a local copy of OVAL. Server mode for easy querying.github.com

goval-dictionary fetch amazon 1 2 2022 2023

 
 

6. Vulsのインストール

ようやくVulsのインストールとなります。

mkdir -p $GOPATH/src/github.com/future-architect
cd $GOPATH/src/github.com/future-architect
git clone https://github.com/future-architect/vuls.git
cd vuls
make install
cd /opt/vuls
vim config.toml

[servers]

[servers.localhost]
host = "localhost"
port = "local"


vuls configtestで成功していればOKです。

[root@vuls-server vuls]# vuls configtest
[Sep 23 16:54:11]  INFO [localhost] vuls-v0.23.4-build-20230922_223515_70fd968
[Sep 23 16:54:11]  INFO [localhost] Validating config...
[Sep 23 16:54:11]  INFO [localhost] Detecting Server/Container OS...
[Sep 23 16:54:11]  INFO [localhost] Detecting OS of servers...
[Sep 23 16:54:11]  INFO [localhost] (1/1) Detected: localhost: amazon 2
[Sep 23 16:54:11]  INFO [localhost] Detecting OS of containers...
[Sep 23 16:54:11]  INFO [localhost] Checking Scan Modes...
[Sep 23 16:54:11]  INFO [localhost] Checking dependencies...
[Sep 23 16:54:11]  INFO [localhost] Dependencies ... Pass
[Sep 23 16:54:11]  INFO [localhost] Checking sudo settings...
[Sep 23 16:54:11]  INFO [localhost] Sudo... Pass
[Sep 23 16:54:11]  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
[Sep 23 16:54:11]  INFO [localhost] Scannable servers are below...
localhost

 
 

7. vulsrepoのインストール

VulsはCUI上でも検知&検知結果の表示ができますが、やはりWEB上で表示できたほうが見やすいのでvulsrepoをインストールします。

mkdir /opt/vuls/results
cd /opt
git clone https://github.com/ishiDACo/vulsrepo.git
cd /opt/vulsrepo/server
cp vulsrepo-config.toml.sample vulsrepo-config.toml

vim vulsrepo-config.toml

[Server]
rootPath = "/opt/vulsrepo"
resultsPath  = "/opt/vuls/results"
serverPort  = "5111"

 
 

8. Vuls,vulsrepoをsystemd化する

こちらの記事を参考にVulsとvulsrepoをsystemctl化させます。
qiita.com

vim /etc/systemd/system/vulsrepo.service

[Unit]
Description=vulsrepo daemon
Documentation=https://github.com/usiusi360/vulsrepo

[Service]
ExecStart = /opt/vuls/vulsrepo/server/vulsrepo-server
ExecRestart = /bin/kill -WINCH ${MAINPID} ; /opt/vulsrepo/server/vulsrepo-server
ExecStop = /bin/kill -WINCH ${MAINPID}
Restart = no
Type = simple
User = root
Group = root

[Install]
WantedBy = multi-user.target
vim /etc/systemd/system/vuls.service

[Unit]
Description=vuls daemon
Documentation=https://github.com/usiusi360/vulsrepo

[Service]
WorkingDirectory=/opt/vuls
ExecStart = /opt/go/bin/vuls server -listen [プライベートIP]:5515 -to-localfile
ExecRestart = /bin/kill -WINCH ${MAINPID} ; /opt/go/bin/vuls server -listen [プライベートIP]:5515 -to-localfile
ExecStop = /bin/kill -WINCH ${MAINPID}
Restart = no
Type = simple
User = root
Group = root

[Install]
WantedBy = multi-user.target
systemctl daemon-reload

systemctl start vulsrepo vuls
systemctl enable vulsrepo vuls
systemctl status vulsrepo vuls

以上でVulsサーバ側の構築は完了です。


それではブラウザからアクセスしてみます。

 
 

9. 脆弱性検知&確認

最後にvulsクライアントを検知してみましょう。

クライアント側にパッケージ情報を送信する方法はcurlコマンドでPOSTするだけなのですが、検知対象のサーバのOSによってリクエストヘッダが異なります。

vuls.io


せっかくなのでシェルにしておきます。

[root@vuls-client bin]# cat vuls-send.sh
#!/bin/bash

VULS_SERVER='[プライベートIP]'
AMAZON_LINUX_RELEASE=$(awk '{if ($0 ~ /Amazon\ Linux\ release\ 2023/) for (i=4; i<=NF; i++) printf("%s ", $i); else if ($0 ~ /Amazon\ Linux\ 2023/) for (i=3; i<=NF; i++) printf("%s ", $i); else if ($0 ~ /Amazon\ Linux\ release\ 2022/) for (i=4; i<=NF; i++) printf("%s ", $i); else if ($0 ~ /Amazon\ Linux\ 2022/) for (i=3; i<=NF; i++) printf("%s ", $i); else if ($0 ~ /Amazon\ Linux\ release\ 2/) printf("%s %s",$4, $5); else if ($0 ~ /Amazon\ Linux\ 2/) for (i=3; i<=NF; i++) printf("%s ", $i); else if (NF==5) print $5}' /etc/system-release)

curl -X POST -H "Content-Type: text/plain" -H "X-Vuls-OS-Family: `awk '{print tolower($1)}' /etc/system-release`" -H "X-Vuls-OS-Release: $AMAZON_LINUX_RELEASE" -H "X-Vuls-Kernel-Release: `uname -r`" -H "X-Vuls-Server-Name: `hostname`" --data-binary "`repoquery --all --pkgnarrow=installed --qf="%{NAME} %{EPOCH} %{VERSION} %{RELEASE} %{ARCH} %{UI_FROM_REPO}"`" http://${VULS_SERVER}:5515/vuls > /dev/null

if [ $? -ne 0 ]; then
  logger 'vuls scan is error.'
fi


スクリプトを実行します。

[root@vuls-client bin]# bash vuls-send.sh
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  113k    0 94355  100 21805  20722   4788  0:00:04  0:00:04 --:--:-- 25512


先ほど送信されたパッケージ情報に対して検知した脆弱性がserverity別に表示されました。


もっと詳細に見ていくと、どのパッケージが検知されたのか、推奨されるパッケージのバージョンも表示されるのはよいですね。