Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
6
Help us understand the problem. What is going on with this article?
@sikkim

Zabbix3.4をdockerで運用してVulsと連携させる 〜 その3 〜 ZabbixとVulsの連携

More than 3 years have passed since last update.

はじめに

その1ではZabbixを、その2ではVulsをインストールしました。

Zabbix3.4をdockerで運用してVulsと連携させる 〜 その1 〜 Zabbixのインストール
Zabbix3.4をdockerで運用してVulsと連携させる 〜 その2 〜 Vulsのインストール

いよいよ両者を連携させてみます。
Software Design 2017年10月号にVulsとZabbixの連携方法が載っているので、そちらを参考にしました。

目標

  • Zabbixのホスト情報からVulsの設定ファイル(config.toml)を自動生成する
  • Vulsのスキャン結果をZabbixへ連携する
  • Zabbixで脆弱性情報を表示する

Zabbix側での事前準備

Zabbixのホスト情報を用いてVulsの設定ファイルを作成するので、スキャン対象のサーバーをZabbixの監視対象にします。

【スキャン対象サーバー側】Zabbix Agentのインストールと設定

この作業はスキャン対象サーバーで行います。

Zabbix Agentをインストールします。

wget http://repo.zabbix.com/zabbix/3.4/ubuntu/pool/main/z/zabbix-release/zabbix-release_3.4-1+trusty_all.deb
sudo dpkg -i zabbix-release_3.4-1+trusty_all.deb
sudo apt-get update
sudo apt-get install zabbix-agent

Zabbix Agentの設定ファイルを編集します。

sudo vim /etc/zabbix/zabbix_agentd.conf

Server=の後ろをZabbixサーバーのIPアドレスに書き換えましょう。

設定が終わったらZabbix Agentを起動します。

sudo /etc/init.d/zabbix-agent start

スキャン対象サーバーをZabbixの監視対象に登録

Zabbixにログインし、設定→ホストから「ホストの作成」をクリックして、監視対象サーバーのIPアドレスを入力します。
テンプレートはTemplete OS LinuxTemplate_Vulsを選択しました。

スクリーンショット 2017-10-05 16.25.52.png

Template_Vulsは以下のURLからダウンロードしてZabbixにインポートしてください。
https://github.com/usiusi360/vuls_autoscan_for_zabbix

config.tomlの自動生成

Zabbixの設定からVulsの設定ファイルを自動生成する方法です。
VulsとZabbixを連携させるだけなら、この章は飛ばしても構いません。

下記URLからcreate_config.shを取得します。
https://github.com/usiusi360/vuls_autoscan_for_zabbix/

wget https://github.com/usiusi360/vuls_autoscan_for_zabbix/raw/master/create_config.sh
wget chmod 700 create_config.sh

ZABBIX_SERVERZABBIX_USERおよびZABBIX_PASSを自分の環境に合わせて書き換えましょう。

url="http://${ZABBIX_SERVER}/zabbix/api_jsonrpc.php"

は以下のように書き換える必要がありました。

url="http://${ZABBIX_SERVER}/api_jsonrpc.php"

実行にはjqが必要なので、入っていなければインストールします。

brew install jq

config.toml.masterを作成します。
create_config.shconfig.toml.masterの内容とZabbixサーバーのホスト情報を組み合わせてconfig.tomlを生成します。

config.toml.master
[default]
port    = "22"
user    = "vuls"
keyPath = "/home/vuls-user/.ssh/id_rsa"

内容は自分の環境に合わせて書き換えてください。

前回作成したconfig.tomlは退避しておきます。

mv config.toml config.toml.back

create_config.shを実行するとconfig.tomlが生成されました。

./create_config.sh
生成されたconfig.toml
[default]
port    = "22"
user    = "vuls"
keyPath = "/home/vuls-user/.ssh/id_rsa"
[servers]
[servers."Zabbix上のホスト名"]
host = "ホストのIPアドレス"

Zabbix上で、ステータスが「有効」でエージェントの状態が正常(緑色)になっているホストの情報だけが追加されます。
私の環境ではなぜかVirtualBox上のUbuntuに入れたZabbix agentをdocker上のZabbix serverからうまく認識できなかったので、別マシンにZabbix agentを入れて確認しました。
Linuxサーバー以外のホスト設定も拾ってしまうので、MacやWindowsのZabbix Agentが存在する環境ではスクリプトを改良する必要があるでしょう。
自動化する必要がなければ、スクリプトを使わずに手で書いた方が手っ取り早いです。

Vulsのスキャン結果をZabbixへ連携する

スクリプトの準備

vuls_autoscan_for_zabbix.shをダウンロードします。

wget https://github.com/usiusi360/vuls_autoscan_for_zabbix/raw/master/vuls_autoscan_for_zabbix.sh
chmod 700 vuls_autoscan_for_zabbix.sh

このスクリプトはローカル環境のVulsを前提としているので、docker上のVulsで動くように以下のように書き換えました。

vuls_autoscan_for_zabbix.sh
#!/bin/bash

ZABBIX_SERVER="localhost"
RETRY=3
PAST_YEAR=2
#PROXY="-http-proxy=http://proxy.hogehoge.co.jp:10080"

SSH_PATH="/Users/username/.ssh"

########################

VULS_HOME=`cd $(dirname $0) && pwd`
#VULS_LOG="${VULS_HOME}/results"
VULS_LOG="/vuls/results"

vuls_comm="docker run --rm --volumes-from vuls-data -v ${SSH_PATH}:/home/vuls-user/.ssh:ro -v ${VULS_HOME}:/vuls/config -v /etc/localtime:/etc/localtime:ro -e TZ=Asia/Tokyo vuls/vuls"
go_cve_dictionary_comm="docker run --rm -it --volumes-from vuls-data vuls/go-cve-dictionary"
goval_dictionary_comm="docker run --rm -it --volumes-from vuls-data vuls/goval-dictionary"

my_logger() {
    local priority="user.info"
    logger -i -p $priority -t `basename $0` "$1"
}

update() {
  local target=$1

  local last_year=`date +%Y`
  local first_year=`expr ${last_year} - ${PAST_YEAR} + 1`
  local years=""
  for i in `seq ${first_year} 1 ${last_year}`
  do
    years="${years} $i"
  done

  for i in `seq 1 ${RETRY}`
  do
    $go_cve_dictionary_comm fetch${target} ${PROXY} -years $years
    if [ $? -eq 0 ];then
      my_logger "[INFO] Update success. [${target}]"
      break
    else
      if [ $i -lt $RETRY ];then
          my_logger "[INFO] Update retry. [${target}] (count=$i)"
          sleep 10
      else
          my_logger "[ERROR] Update retry over. [${target}] (count=$i)"
      fi
    fi
  done
}

update_oval() {
  local target=$1
  local option="$2"

  for i in `seq 1 ${RETRY}`
  do
    $goval_dictionary_comm fetch-${target} ${PROXY} ${option}
    if [ $? -eq 0 ];then
      my_logger "[INFO] Update-OVAL success. [${target}]"
      break
    else
      if [ $i -lt $RETRY ];then
          my_logger "[INFO] Update-OVAL retry. [${target}] (count=$i)"
          sleep 5
      else
          my_logger "[ERROR] Update-OVAL retry over. [${target}] (count=$i)"
      fi     
    fi
  done
}

scan(){
  $vuls_comm scan -deep -config=/vuls/config/config.toml -ssh-native-insecure
    if [ $? -eq 0 ];then
      my_logger "[INFO] Scan success."
    else
      my_logger "[ERROR] Scan fail."
      exit 1
    fi
}


report(){
  $vuls_comm report -format-json -cvedb-path=/vuls/cve.sqlite3 -ovaldb-path=/vuls/oval.sqlite3 -format-short-text -config=/vuls/config/config.toml -lang=ja
    if [ $? -eq 0 ];then
      my_logger "[INFO] Scan success."
      rm -rf ${VULS_LOG}
      docker cp vuls-data:/vuls/results ${VULS_LOG}
    else
      my_logger "[ERROR] Scan fail."
      exit 1
    fi
}

send_zabbix(){
  files="${VULS_LOG}/current/*.json"
  for filepath in $files; do
    TARGET_NAME=`basename $filepath .json`
    if [ "${TARGET_NAME}" == "all" ]; then
      continue
    fi
      zabbix_sender -z ${ZABBIX_SERVER} -s ${TARGET_NAME} -k nvd_count -o `cat $filepath | jq '.ScannedCves? | length'`
      zabbix_sender -z ${ZABBIX_SERVER} -s ${TARGET_NAME} -k nvd_max -o `cat $filepath | jq '[.ScannedCves[] | .CveContents.nvd.Cvss2Score]+[0] | max'`
   done
}

rotate(){
  firstDay=`date '+%Y-%m-01'`
  agoYear=`date -d "$firstDay 1 months ago" '+%Y'`
  agoMonth=`date -d "$firstDay 1 months ago" '+%m'`
  mkdir ${VULS_LOG}/$agoYear-$agoMonth > /dev/null 2>&1
  mv ${VULS_LOG}/$agoYear$agoMonth* ${VULS_LOG}/$agoYear-$agoMonth > /dev/null 2>&1
}


#======

cd ${VULS_HOME} 
  if [ $? -ne 0 ];then
    my_logger "[ERROR] path not found [${VULS_HOME}]"
    exit 1
  fi

## update ##
update nvd
update jvn

## update oval ##
#update_oval redhat "5 6 7"
#update_oval debian "7 8 9 10"
#update_oval ubuntu "12 14 16"
#update_oval oracle

## vuls scan ##
scan

## vuls report ##
report

## send zabbix ##
send_zabbix

## rotate ##
#rotate

exit 0

ZABBIX_SERVERSSH_PATHは環境に合わせて書き換えてください。
コメントアウトは必要に応じて外してください。
rotateはdocker用に修正していないので、コメントアウトを外しても正常に動かないはずです。

(2017/10/12追記) 最初、dockerに-itオプションを付けていましたが、cronから実行すると"the input device is not a TTY"というエラーが出て動かなかったため、外しました。

スキャン結果格納用フォルダの作成

Vulsのスキャン結果を格納するフォルダを作成します。
/vuls/results/currentが絶対パスのリンクになっているので、絶対パスで作らないと動きません。
改良したいところです。

sudo mkdir /vuls
sudo chmod 777 /vuls

zabbix_senderのインストール

スクリプトの実行にはzabbix_senderが必要です。
残念ながら公式dockerイメージはないようなのでローカルにインストールします。

Macでは--without-server-proxyオプション付きでzabbixをインストールすると、Zabbix Agentのみがインストールされますが、この時zabbix_senderも一緒にインストールされます。

brew install --without-server-proxy zabbix

Zabbix連携スクリプトの実行

./vuls_autoscan_for_zabbix.sh

スクリプトを実行すると以下の処理が行われます。

  • 脆弱性データベースの更新(NVD, JVN)
  • OVALデータの更新(コメントアウトを外した場合)
  • スキャン実行
  • レポート作成
  • Zabbixへレポートを連携

正常に連携が完了するとZabbix側でmax vulnerability(脆弱性スコアの最大値)とnumber of vulnerabilities(脆弱性の件数)が更新されます。
スクリーンショット 2017-10-06 16.01.10.png

前回チェック時から検知数が増えた場合にアラートが上がります。
スクリーンショット 2017-10-06 16.24.23.png

グラフも表示できます。
これはapt-get upgradeを行った直後にスクリプトを動かした結果です。
脆弱性の件数が減っていることがわかりますね。
スクリーンショット 2017-10-06 16.19.24.png

あとはスクリプトをcronで毎日実行すれば脆弱性の検知はばっちりですね。

課題

  • Vuls設定ファイルの自動生成スクリプト
    • Zabbix上の設定からVulsの設定ファイルを生成する際に、Vuls未対応のOSでも生成されてしまう
  • Zabbix連携スクリプト
    • zabbix_senderもdockerで動かしたい(公式イメージにこだわらなければある)
    • Vulsのスキャン結果を任意の場所に格納できるようにしたい
  • Vuls本体
    • Mac上のdockerコンテナもVulsのスキャン対象にできればいいのに(Linux上のコンテナはスキャン可能)
      • 今はホストOSがVuls非対応の時点でエラーになってコンテナスキャンされない
      • ホストOSはスキャンせず、コンテナだけスキャン対象にするオプションができれば解決

最後に

ZabbixとVulsは単独でも強力なツールですが、組み合わせるといっそう便利になります。
Docker上で動かせば、環境の移行も楽ですよ。

6
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
sikkim
サーバーサイドエンジニア。情報処理安全確保支援士(登録番号:020092)。PythonやNode.js、FileMaker、Nuxt.jsで開発することが多いです。

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
6
Help us understand the problem. What is going on with this article?