Vuls Serverでssh接続不要なセキュリティ脆弱性通知の仕組みを作った

こちらの内容は・・・
・上司からセキュリティ脆弱性の運用を内製化したいがお金はかけたくないと言われ
・エージェントレスだから行けると思ったら、上司からssh接続するなんてありえないと言われ
・運用担当から、Vulsのデフォルトの通知方法ではやりたくないと駄々をこねらてしまった

・・・こんな人向け

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207381/cb21f847-c7e9-a31b-bc07-54f6de9eddf5.png" width=25%>


####できること
・Vuls Serverを用いたセキュリティ脆弱性通知の環境を構築
・１日１回、CVE情報（cvss3）の更新とVuls Report通知を行う
・前日のReportの結果に差分がある場合のみメール通知＆バックログに通知する
・Target Serverにある特定のパッケージ情報（kernelやhttpd等）だけを通知する

####環境
・AWS上に構築したCentos７
・Vuls 0.5.0


####構成
・ざっくりとこんな構成で作った
<img width="937" alt="スクリーンショット 2019-06-02 20.16.30.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207381/430853f9-384e-0260-aaff-0fd70f5ff8de.png">



####作業内容
1.CentoOS7サーバー用意
2.go-cve-directionaryのセットアップ
3.Vuls本体のセットアップ
　※おまけでVuls Report導入
4.CVE情報取得用のスクリプト作成
5.メール通知用のスクリプト作成
6.TargetServerにパッケージ取得用のスクリプト作成

1.CentoOS7サーバー用意
初期設定は割愛、Mail送信環境の準備から記載

■Postfixインストール

```bash:
# yum install postfix mailx
# cp -p /etc/postfix/main.cf{,.org}
```

■SMTP AUTHの設定

```bash:
$ sudo yum install cyrus-sasl*
$ sudo sasldblistusers2
$ sudo saslpasswd2 -u [xxxx.jp] -c [password]

 
$ systemctl status saslauthd
$ sudo sasldblistusers2
$ sudo chmod 777 /etc/sasldb2
$ cp -p /etc/postfix/main.cf /etc/postfix/main.cf.org
# sudo vi /etc/postfix/main.cf
'--------------------------------
##mydestination = $myhostname, localhost.$mydomain, localhost
relayhost = [セキュリティ脆弱性スクリプトがあるサーバのプライベートIP]

##Vuls
smtpd_sasl_auth_enable = yes
smtpd_sasl_local_domain = [xxxx.jp]
smtpd_recipient_restrictions=
permit_mynetworks,
permit_sasl_authenticated,
smtpd_sasl_security_options = noanonymous
broken_sasl_auth_clients = yes
'--------------------------------

$ sudo vim /etc/sasl2/smtpd.conf
'--------------------------------
#pwcheck_method: sasldb
#pwcheck_method: saslauthd
pwcheck_method: auxprop	★変更　→　Cyrus SASL パスワードファイルを利用
'--------------------------------
```
■golangのインストール

```bash:
$ su -
# curl -O https://dl.google.com/go/go1.11.linux-amd64.tar.gz
# tar vzfx go1.11.linux-amd64.tar.gz

# mv go /usr/local/
# export GOROOT=/usr/local/go
# export GOPATH=$HOME/go
# export PATH=$PATH:$HOME/go:$GOROOT/bin:$GOPATH/bin

# vim .bash_profile
'-------------------------------------
GOPATH=$HOME/go
GOROOT=/usr/local/go
PATH=$PATH:$HOME/.local/bin:$HOME/bin:$GOROOT/bin:$GOPATH/bin
 '-------------------------------------
# source .bash_profile
```
2.go-cve-directionaryのセットアップ

```bash:
# su - vuls
$ export GOROOT=/usr/local/go
$ export GOPATH=$HOME/go
$ export PATH=$PATH:$HOME/go:$GOROOT/bin:$GOPATH/bin:$VULSREPO

$ vim .bash_profile
'-------------------------------------
GOPATH=$HOME/go
GOROOT=/usr/local/go
VULSREPO=$GOPATH/src/github.com/future-architect/vulsrepo/server
PATH=$PATH:$HOME/.local/bin:$HOME/bin:$GOROOT/bin:$GOPATH/bin:$VULSREPO

 '-------------------------------------
$ source .bash_profile

$ mkdir -p $GOPATH/src/github.com/kotakanbe
$ cd $GOPATH/src/github.com/kotakanbe
$ git clone https://github.com/kotakanbe/go-cve-dictionary.git

$ mkdir
$ go get -u $GOPATH/src/github.com/golang/dep/cmd/dep
$ cp -p /home/go/bin/dep $GOPATH
$ ¥cp -pr /home/go/src/github.com/golang/ /usr/local/go/bin/src/
$ rm -rf /home/go
$ cd $GOPATH/src/github.com/kotakanbe/go-cve-dictionary
$ make install
$ ln -s /home/vuls/oval.sqlite3 .
```
■OVAL(Redhat)から取得

```bash:
#cd $GOPATH/src/github.com/kotakanbe
#ll /home/go/src/github.com/kotakanbe

#git clone https://github.com/kotakanbe/goval-dictionary.git
#cd goval-dictionary
#make install
```

◆CVEデータベース構築



OVALから取得

```bash:
$ goval-dictionary fetch-redhat 7
$ ln -s /home/vuls/results  /home/vuls/go/src/github.com/future-architect/vulsrepo/results
$ ln -s /home/vuls/config.toml /home/vuls/go/src/github.com/future-architect/vulsrepo/config.toml
$ ln -s /home/vuls/cve.sqlite3  /home/vuls/go/src/github.com/future-architect/vulsrepo/cve.sqlite3
$ ln -s /home/vuls/oval.sqlite3  /home/vuls/go/src/github.com/future-architect/vulsrepo/oval.sqlite3 
```

【参考】
JVNから取得

```bash:
$ for i in {2017..2018}; do go-cve-dictionary fetchjvn -years $i; done
```
NVDから取得

```bash:
$ for i in {2017..2018}; do go-cve-dictionary fetchnvd -years $i; done
```

３.vuls本体のセットアップ

```bash:
#su - vuls
$ cd
$ mkdir vuls
$ cd 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


$ vim /home/vuls/config.toml
'-------------------------------
[email]
smtpAddr = "localhost"
smtpPort = "25"
user = "vuls@xxxx.jp"
password = "XXXXXX"
from = "vuls@xxxx.jp"
to = ["xxxxxxxxxxxx@xx.backlog.jp"] ※バックログ通知用のメールアドレス
to = ["xxxx-alert@xxxx.com"]
'-------------------------------

$ vuls configtest
```

■ログオフ後もVuls Serverが動くよう起動

```
$ nohup vuls server -listen 0.0.0.0:5515 -to-localfile -format-json &
```

※おまけ
■vuls reportのセットアップ

```bash:
# yum install httpd
# systemctl start httpd
# systemctl enable httpd
# su - vuls

$ cd $GOPATH/src/github.com/future-architect
$ git clone https://github.com/usiusi360/vulsrepo.git
$ cp -p  $GOPATH/src/github.com/future-architect/vulsrepo/server/vulsrepo-config.toml.sample $GOPATH/src/github.com/future-architect/vulsrepo/server/vulsrepo-config.toml

$ vim $GOPATH/src/github.com/future-architect/vulsrepo/server/vulsrepo-config.toml
------------------
[Server]
rootPath = "/home/vuls/vulsrepo"
resultsPath  = "/home/vuls/results"
serverPort  = "5111"
------------------

$ cd
$ export VULSREPO=$GOPATH/src/github.com/future-architect/vulsrepo/server
$ vim .bash_profile
'-------------------------------------
GOPATH=$HOME/go
GOROOT=/usr/local/go
VULSREPO=$GOPATH/src/github.com/future-architect/vulsrepo/server
PATH=$PATH:$HOME/.local/bin:$HOME/bin:$GOROOT/bin:$GOPATH/bin:$VULSREPO
 '-------------------------------------
$ source .bash_profile
$ vulsrepo-server
```

■ログオフ後もVuls Reportが動くよう起動

```bash:
$ nohup /home/vuls/vulsrepo/server/vulsrepo-server &
```

4.CVE情報取得用のスクリプト作成
CVE情報をovalから取得する。
下記の場合対象はRedHat5〜7となる。
cronで日次起動設定する。

```bash:update_cve_dictionary.sh

#!/bin/sh
##
## Update CVE Dictionary for Vuls
##https://github.com/kotakanbe/goval-dictionary
##

############################################
# 変数
############################################
HOSTNAME=${HOSTNAME}
LOCK_FILE=/opt/tools/key_lock/${HOSTNAME}.`basename $0`.locked
LOCKED_FILE=/opt/tools/key_locked/${HOSTNAME}.`basename $0`.locked
LOG_FILE=/var/log/tools/goval-dictionary_${HOSTNAME}.log

GOVAL_DIC="fetch-redhat"
GOVAL_DIR="-dbpath=/home/vuls/oval.sqlite3"
GOVAL_VER="5 6 7"
############################################
# 処理
############################################
echo `date +%Y%m%d_%H:%M:%S` Update_start >> ${LOG_FILE}

if [ ! -f ${LOCKED_FILE} ];then

        /usr/bin/touch ${LOCK_FILE}
        /usr/bin/mv ${LOCK_FILE} ${LOCKED_FILE}

        #Update CVE Dictionary for Vuls
        CDV=`/home/vuls/go/bin/goval-dictionary ${GOVAL_DIC} ${GOVAL_DIR} ${GOVAL_VER}`
        CDV_CHECK=$?

        if [ ${CDV_CHECK} = "0" ] ;then

                echo `date +%Y%m%d_%H:%M:%S` Update_complete >> ${LOG_FILE}

        else

                echo `date +%Y%m%d_%H:%M:%S` Update_failed >> ${LOG_FILE}

                /usr/bin/mv ${LOCKED_FILE} ${LOCK_FILE}

                exit 1
        fi



        /usr/bin/mv ${LOCKED_FILE} ${LOCK_FILE}

        exit
else

        echo `date +%Y%m%d_%H:%M:%S` Aleady Running >> ${LOG_FILE}

fi

exit
```

5.メール通知用のスクリプト作成
前回とのReportとの差分を比較し
差分があった場合はCVEのデータベース（oval）の内
CVSSのレベル７以上のものを通知する。
cronで日次起動設定する。

```bash:vuls_notification_script.sh

#!/bin/sh
##Vuls Notification Script
##https://vuls.io/docs/en/usage-server.html
##

############################################
# 変数
############################################
HOSTNAME=${HOSTNAME}
LOCK_FILE=/opt/tools/key_lock/${HOSTNAME}.`basename $0`.locked
LOCKED_FILE=/opt/tools/key_locked/${HOSTNAME}.`basename $0`.locked
LOG_FILE=/var/log/tools/vuls_notification_script_${HOSTNAME}.log
CONFIG="-config=/home/vuls/config.toml"
DB_TYPE="-ovaldb-type=sqlite3"
DB_DIR="-ovaldb-sqlite3-path=/home/vuls/oval.sqlite3"
FORMAT1=" -format-list"
FORMAT2="-format-one-email -format-one-line-text"
THRESHOLD="--cvss-over=7"
LANG="-lang=ja"
RESULTS_DIR="/home/vuls/results/"
OUTPUT="-to-email"
OUTPUT1=`date +%Y%m%d`_report.txt
OUTPUT2=` date --date '1 day ago' +%Y%m%d`_report.txt
OUTPUT3=`date +%Y%m%d`_report_check.txt
OUTPUT4=` date --date '1 day ago' +%Y%m%d`_report_check.txt

############################################
# 関数
############################################

function VULS_DIFF_CHECK (){

        #VULS DIFF_REPORT
        /home/vuls/go/bin/vuls report ${CONFIG} ${DB_TYPE} ${DB_DIR} ${FORMAT1} ${THRESHOLD} ${LANG} >${RESULTS_DIR}${OUTPUT1}

	/bin/grep "|" ${RESULTS_DIR}${OUTPUT1}| /bin/awk -F '|' '{print $2,$4,$7}'| /bin/md5sum | /bin/awk '{print $1} ' > ${RESULTS_DIR}${OUTPUT3}
        VULS_DIFF_REPORT_CHECK=$?

        if [ ${VULS_DIFF_REPORT_CHECK} = "0" ] ;then

                echo `date +%Y%m%d_%H:%M:%S` vusl_diff_report_complete >> ${LOG_FILE}

        else

                echo `date +%Y%m%d_%H:%M:%S` vusl_diff_report_failed >> ${LOG_FILE}

                /bin/mv ${LOCKED_FILE} ${LOCK_FILE}

                exit
        fi

        #DIFF_CHECK
        echo `date +%Y%m%d_%H:%M:%S` diff_check_start >> ${LOG_FILE}

        /bin/diff -q ${RESULTS_DIR}${OUTPUT3} ${RESULTS_DIR}${OUTPUT4}
        DIFF=$?

        if [ $DIFF = 0 ] ;then

                echo `date +%Y%m%d_%H:%M:%S` diff_check_complete >> ${LOG_FILE}
                echo `date +%Y%m%d_%H:%M:%S` vuls_report_end >> ${LOG_FILE}

                /bin/mv ${LOCKED_FILE} ${LOCK_FILE}

                exit

        elif [ $DIFF = 1 ] ;then

                echo `date +%Y%m%d_%H:%M:%S` diff_check_complete >> ${LOG_FILE}

                VULS_REPORT
                GENERATION_MANAGING
        else
                echo `date +%Y%m%d_%H:%M:%S` diff_check_failed >> ${LOG_FILE}

                /bin/mv ${LOCKED_FILE} ${LOCK_FILE}

                exit
        fi
}

function VULS_REPORT (){
        /home/vuls/go/bin/vuls report ${CONFIG} ${DB_TYPE} ${DB_DIR} ${FORMAT2} ${THRESHOLD} ${LANG} ${OUTPUT}
        VULS_REPORT_CHECK=$?

        if [ ${VULS_REPORT_CHECK} = "0" ] ;then

                echo `date +%Y%m%d_%H:%M:%S` vusl_report_complete >> ${LOG_FILE}

        else

                echo `date +%Y%m%d_%H:%M:%S` vusl_report_failed >> ${LOG_FILE}

                /bin/mv ${LOCKED_FILE} ${LOCK_FILE}

                exit
        fi
}

function GENERATION_MANAGING (){

        echo `date +%Y%m%d_%H:%M:%S` generation managin_start >> ${LOG_FILE}

        /bin/find ${RESULTS_DIR}* -type f -mtime +7 -exec /bin/rm -f {} \;
        GM=$?

        if [ $GM = 0 ] ;then

                echo `date +%Y%m%d_%H:%M:%S` generation managing_complete >> ${LOG_FILE}

        else

                echo `date +%Y%m%d_%H:%M:%S` generation managing_failed >> ${LOG_FILE}

                /bin/mv ${LOCKED_FILE} ${LOCK_FILE}

                exit
        fi
}
############################################
# 処理
############################################
echo `date +%Y%m%d_%H:%M:%S` vusl_report_start >> ${LOG_FILE}

if [ ! -f ${LOCKED_FILE} ];then

        /bin/touch ${LOCK_FILE}
        /bin/mv ${LOCK_FILE} ${LOCKED_FILE}

        VULS_DIFF_CHECK 

        /bin/mv ${LOCKED_FILE} ${LOCK_FILE}

else

        echo `date +%Y%m%d_%H:%M:%S` Aleady Running >> ${LOG_FILE}

fi

echo `date +%Y%m%d_%H:%M:%S` vusl_report_end >> ${LOG_FILE}
exit
```

6.TargetServerにパッケージ取得用のスクリプト作成
Target ServerからVuls Serverにパッケージ情報をpostする。
対象は、tg-rpm.txt記載のものとなる。
cronで日次起動設定する。

```bash:vuls_one_liner_scan.sh
#!/bin/sh
##
##Vuls One liner scan
##https://vuls.io/docs/en/usage-server.html
##

############################################
# 変数
############################################
#HOSTNAME=${HOSTNAME}
LOCK_FILE=/tools/vuls/key_lock/${HOSTNAME}.`basename $0`.locked
LOCKED_FILE=/tools/vuls/key_locked/${HOSTNAME}.`basename $0`.locked
LOG_FILE=/var/log/tools/vuls_scan_${HOSTNAME}.log

CT=text/plain
XVOF=`awk '{print tolower($1)}' /etc/redhat-release`
XVOR=`awk '{print $4}' /etc/redhat-release`
TG_RPM=/tools/vuls/tg-rpm.txt
XVKR=`uname -r`
RPM_DATA=`rpm -qa --queryformat "%{NAME} %{EPOCHNUM} %{VERSION} %{RELEASE} %{ARCH}\n"|grep -f ${TG_RPM}`
VULS_SERVER=http://[vuls server IP address]:5515/vuls

############################################
# 処理
############################################
echo `date +%Y%m%d_%H:%M:%S` vusl_scan_start >> ${LOG_FILE}

if [ ! -f ${LOCKED_FILE} ];then

        /usr/bin/touch ${LOCK_FILE}
        /usr/bin/mv ${LOCK_FILE} ${LOCKED_FILE}

        #VULS SCAN
        VULS_SCAN=`curl -X POST \
        -H "Content-Type: ${CT}" \
        -H "X-Vuls-Server-Name: ${HOSTNAME}" \
        -H "X-Vuls-OS-Family: ${XVOF}" \
        -H "X-Vuls-OS-Release: ${XVOR}" \
        -H "X-Vuls-Kernel-Release: ${XVKR}" --data-binary "${RPM_DATA}" ${VULS_SERVER}`

        VULS_SCAN_CHECK=$?

        if [ ${VULS_SCAN_CHECK} = "0" ] ;then

                echo `date +%Y%m%d_%H:%M:%S` vusl_scan_complete >> ${LOG_FILE}

        else

                echo `date +%Y%m%d_%H:%M:%S` vusl_scan_failed >> ${LOG_FILE}

                /usr/bin/mv ${LOCKED_FILE} ${LOCK_FILE}

                exit
        fi

        /usr/bin/mv ${LOCKED_FILE} ${LOCK_FILE}

        exit
else

        echo `date +%Y%m%d_%H:%M:%S` Aleady Running >> ${LOG_FILE}

fi

exit
```

tg-rpm.txtの例

```bash:tg-rpm.txt
kernel
httpd
```




####参考にさせていただいたサイト/記事
https://vuls.io/docs/ja/tips.html
https://qiita.com/ike_dai/items/6e5fe881646e00beafbd
https://sys-guard.com/post-15166/
https://qiita.com/sadayuki-matsuno/items/0bb8bb1689425bb9a21c
https://qiita.com/madamadaikeru22/items/59bb2b4201a0a5646485
https://qiita.com/usiusi360/items/aeb3cd3630badfacdb4e
https://www.slideshare.net/TakayukiUshida/vuls-102299967