Vulsを使った脆弱性チェック運用はじめるよ
という事で、背景は前の記事で書いた通りですので、実際に環境を構築してみます。 複数アカウントにまたがる環境、且つIPアドレスが結構変動する環境では通常通りのconfigではすんなり動いてくれないため、力業で解決しているところもあります。
当面はIPアドレスが変動してもconfigに反映出来る仕組み作りです。
では、実際に今どんな環境で動いているか見てみましょう。 基本は、公式の内容通りで環境構築をしていますが、レコチョク内での運用を加味しています。
目的
- 稼働中サーバのOSパッケージ脆弱性を可視化し、特に対応が必要なものをあぶりだす。
環境構成
環境Directory
/home/vulsuser/
※()内はPermission、記載が無い場合は上位継承
- .ssh (700) [各環境の公開鍵置き場]
- accout-xxx (700) [ アカウント名毎にDirectory ]
- xxx_rsa (600) [ アカウント名毎の秘密鍵 ]
- xxx_rsa.pub (644) [ アカウント名毎の公開鍵 ]
- known_hosts (644) [ vulsuserのknown_hosts ]
- config (644) [ 確認無しでknow_hostsを上書きするために設定 ]
- accout-xxx (700) [ アカウント名毎にDirectory ]
- go (775) [ golangの各種sourceやpackage置き場($GOPATHはここ) ]
- bin
- pkg
- src
- github.com
- future-architect
- vuls [ vulsのgit clone ]
- future-architect
- golang
- kotakanbe
- go-cve-dictionary [ go-cve-dictionaryのgit clone ]
- goval-dictionary [ goval-dictionaryのgit clone ]
- github.com
- results (700) [ scan結果確認Directory ]
- yyyy-mm-ddTxx:xx:xx+xx:xx [ vuls scan結果(実行時のタイムスタンプがDirectory名) ]
- current (777) [ 最新のscan結果へのsymbolic link ]
- src (775) [ DLしたFile置き場 ]
- vuls_config(700)
- config.toml (600) [ vuls scan用config ]
- config.toml (600) [ vuls scan用config ]
- vulsrepo (775) [ VulsRepo一式 ]
- .git
- dist
- gallery
- plugins
- server
- vulsrepo-config.toml (664) [ VulsRepo用config ]
- vulsrepo-server [ VulsRepo本体 ]
- index.html (664) [ VulsRepo画面 ]
- cve.sqlite3 (644) [ CVE情報データベース ]
- cve.sqlite3-shm (644) [ CVE情報データベース ]
- cve.sqlite3-wal (644) [ CVE情報データベース ]
- oval.sqlite3 (644) [ OVAL情報データベース ]
- fetchdata.sh (700) [ cron用shell ]
- scan.sh (700) [ cron用shell ]
- slack_notify.sh (700) [ scan結果Slack通知用shell ]
- target_host_list (664) [ scan対象ホストリスト(scan.sh実行結果) ]
環境構築手順
1. 事前準備
- vuls実行ユーザ作成 [ rootで実行 ]
# useradd vulsuser # visudo 以下追加 vulsuser ALL=(ALL) NOPASSWD:ALL - 必要パッケージのインストール [ rootで実行 ]
# yum install -y sqlite git gcc make wget # cd /home/vulsuser/src/ # wget https://storage.googleapis.com/golang/go1.8.3.linux-amd64.tar.gz # tar -C /usr/local -xzf go1.8.3.linux-amd64.tar.gz # vi /etc/profile.d/goenv.sh 以下追加 export GOROOT=/usr/local/go export GOPATH=$HOME/go export PATH=$PATH:$GOROOT/bin:$GOPATH/bin # source /etc/profile.d/goenv.sh # go version バージョン見えていたらOK- golangは1.8.3以上を入れる事 [ https://golang.org/doc/install ]
2. Vulsインストール
- go-cve-dictionaryインストール [ vulsuserで実行 ]
# sudo mkdir /var/log/vuls # sudo chown vulsuser /var/log/vuls # sudo chmod 700 /var/log/vuls # mkdir $HOME/go # mkdir -p $GOPATH/src/github.com/kotakanbe # cd $GOPATH/src/github.com/kotakanbe # git clone https://github.com/kotakanbe/go-cve-dictionary.git # cd go-cve-dictionary # make install # go-cve-dictionary -v バージョン確認が出来ればOK - NVDとJVNのデータをダウンロード
- これが結構時間かかる(10min程度) この初回実行以降は差分ダウンロードとなるため、時間は短くなる
# for i in `seq 2002 $(date +"%Y")`; do go-cve-dictionary fetchnvd -years $i; done # for i in `seq 1998 $(date +"%Y")`; do go-cve-dictionary fetchjvn -years $i; done NVDは2002年以降、JVNは1998年以降のデータを取得 - goval-dictionaryインストール [ vulsuserで実行 ]
# cd $GOPATH/src/github.com/kotakanbe # git clone https://github.com/kotakanbe/goval-dictionary.git # cd goval-dictionary # make install # goval-dictionary -v バージョン確認が出来ればOK- OVALデータをダウンロード
# goval-dictionary fetch-redhat 5 6 7 # goval-dictionary fetch-ubuntu 12 14 16 # goval-dictionary fetch-debian 7 8 9 10 公開されているものの内、RedHat(CentOS)/Ubuntu/Debian分を取得する ※AmazonLinuxは無い - Vuls本体インストール [ vulsuserで実行 ]
# 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 # vuls -v バージョン確認が出来ればOK - Vuls config設定 [ vulsuserで実行 ]
# cd $HOME/vuls_config # vi config.toml # chmod 600 config.toml
3. VulsRepoインストール
- VulsRepo本体インストール [ vulsuserで実行 ]
# cd $HOME # git clone https://github.com/usiusi360/vulsrepo.git - VulsRepo config設定 [ vulsuserで実行 ]
# cd $HOME/vulsrepo/server # vi vulsrepo-config.toml vulsrepo-config.tomlを参考に記載 - VulsRepo起動 [ vulsuserで実行 ]
# sudo /home/vulsrepo/server/vulsrepo-server & 80/tcpなどの予約されているポートでListenさせる場合はsudoしないと起動しない バックグラウンドで実行させる事
最新バージョンではinit.dやsystemctl利用できるようになりましたね。
脆弱性スキャンの実行方法
- 前提条件
- config設定は完了しているものとする
- コマンド実行はvulsuserで行うものとする
- 作業ディレクトリは、$HOMEとする
- VulsRepoは起動中とする
- コンフィグテスト
# vuls configtest -config=vuls_config/config.toml 出力されたホスト名が、スキャン実行可能な対象となる configに記載があるものの出力されなかった場合は、チェック対象側含め設定に不備がある可能性があるため確認する事- エラー含めた詳細は、/var/log/vuls/配下にホスト名毎のログが出力されるため、内容を確認出来る
- スキャンの実行
# vuls scan -config=vuls_config/config.toml スキャン結果が、$HOME/resultsディレクトリに出力される- エラーが出る場合はログを確認する事
- 現在configtestでエラーとなった対象を含むスキャンを実行すると色々コケるため、スキャン対象を明示的に指定して回避する
# vuls scan -config=vuls_config/config.toml [host名.1] [host名.2]... ex) # vuls scan -config=vuls_config/config.toml server01 server02 ... configtestの結果で出力される対象をそのまま連結すればOK - スキャン結果の確認
- ターミナル上で確認する
- vuls reportコマンド実行時にエラーとなる場合は、scanで何らかのエラーが発生している可能性があるので、scanから再実行となる
# vuls report -config=vuls_config/config.toml -format-short-text 簡易版のサマリー # vuls report -config=vuls_config/config.toml -format-full-text 省略無しの結果 # vuls tui -config=vuls_config/config.toml 少しGUIに近い(BIOS設定みたいな感じ)- VulsRepoで確認する
# vuls report -config=vuls_config/config.toml -format-json コマンド実行後、VulsRepoにブラウザで接続すると、ブラウザ上で結果を確認出来る - ターミナル上で確認する
cron
- 環境
# Fetch NVD/JVN Data 00 8 * * 1 su - vulsuser -c "cd /home/vulsuser && ./fetchdata.sh >/dev/null 2>&1" # Vuls Scan 00 9 * * 1 su - vulsuser -c "cd /home/vulsuser/ && ./scan.sh >/dev/null 2>&1" # Vuls ScanData Notify to Slack 30 9 * * 1 su - vulsuser -c "cd /home/vulsuser/ && ./slack_notify.sh >/dev/null 2>&1"- 毎週月曜日08:00に、脆弱性データベースの更新shellを実行
- 毎週月曜日09:00に、脆弱性スキャンshellを実行
- Slackへの結果通知が本番環境と被ると遅延するため、時間調整を実施 (結果通知用shellを実行)
- 実行shell
- fetchdata.sh
- NVDデータベースを、直近2年分の更新
- JVDデータベースを、差分更新
- OVALデータを更新 (RedHat5,6,7/Ubuntu12,14,16/Debian7,8,9,10)
- scan.sh
- reportエラー抑止のため、configtestを利用してscan対象ホストの抽出
- 抽出した対象ホストへscanの実行
- VulsRepo用にscan結果をJSONフォーマットへ変換
- slack_notify.sh
- スキャン後すぐにSlackへ結果を通知すると、データが大量すぎてロストする場合があるため、Slack連携処理を実行
- ホスト毎にCVSS Score 7以上の検出結果を日本語で出力
- fetchdata.sh
Vulsアップデート
細かいバグフィクスやバージョンアップは行われているので、適度に確認をする事
※大型アップデート(v0.3.0 -> v0.4.0みたいな)の場合は、仕様が変わっている可能性があるため、公式を確認する事 Vuls GitHub
- go-cve-dictionaryのバージョンアップ [ vulsuserで実行 ]
# cd $GOPATH/src/github.com/kotakanbe/go-cve-dictionary # git pull # rm -r vendor # make install エラーが出る場合は、$GOPATH/pkg を削除して再度試してみる事 - goval-dictionaryのバージョンアップ [ vulsuserで実行 ]
# cd $GOPATH/src/github.com/kotakanbe/goval-dictionary # git pull # rm -r vendor # make install エラーが出る場合は、$GOPATH/pkg を削除して再度試してみる事 - vulsのバージョンアップ [ vulsuserで実行 ]
# cd $GOPATH/src/github.com/future-architect/vuls # git pull # rm -r vendor # make install エラーが出る場合は、$GOPATH/pkg を削除して再度試してみる事
AWSアカウント追加時の対応
レコチョクでは、100弱のAWSアカウントを運用しているため、AWSアカウント毎にグルーピングし、公開鍵運用を行う事にしました
という事で、AWSアカウントを追加した場合は、vulsuser接続用の公開鍵を作成し配布
- 公開鍵の作成 [ vulsuserで実行 ]
# cd $HOME/.ssh # mkdir account-xxx 追加するアカウント名のディレクトリを作成する # chmod 700 account-xxx 作成したディレクトリのpermissionを変更する # cd account-xxx 作成したディレクトリへ移動する # ssh-keygen -t rsa Generating public/private rsa key pair. Enter file in which to save the key (/home/vulsuser/.ssh/id_rsa): /home/vulsuser/.ssh/account-xxx/xxx_rsa Enter passphrase (empty for no passphrase):なし Enter same passphrase again:なし Your identification has been saved in /home/vulsuser/.ssh/account-xxx/xxx_id_rsa. 以上で、秘密鍵と公開鍵が作成される- 秘密鍵のpermissionは600、公開鍵のpermissionは644になっているか確認しておく事
- 公開鍵の配布とスキャン対象ホスト側設定追加
作成した公開鍵をスキャン対象ホストに以下を設定
- スキャン対象ホスト側設定
スキャン対象ホストで設定が完了したら、vulshostサーバ側から疎通確認を行う(rootで実行) # useradd vulsuser scan実行用ユーザの作成 # visudo 以下の通り追記 vulsuser ALL=(root) NOPASSWD:/usr/bin/yum, /bin/echo # su - vulsuser (ここからvulsuserで実行) # cd $HOME # mkdir .ssh # chmod 755 .ssh/ # cd .ssh このディレクトリ配下に、authorized_keysとして、公開鍵を配置 # chmod 600 authorized_keys # exit (ここからrootで実行) # vi /etc/ssh/sshd_config 以下部分コメントを外す PubkeyAuthentication yes # /etc/rc.d/init.d/sshd stop && /etc/rc.d/init.d/sshd start sshdの再起動- vulshostサーバ側疎通確認
# (vulsuserで実行) # cd $HOME/.ssh/account-xxx 接続確認先ホストが稼働しているAWSアカウントのディレクトリへ移動 # ssh vulsuser@xxx.xxx.xxx.xxx -i xxx_id_rsa 対象ホストへvulsuserで、秘密鍵利用で接続を行う パスワードなしで接続が出来たら、疎通確認OK
接続試行時にパスワードが求められる場合は、対象ホスト側のファイルやディレクトリのpermission、所有者(rootになっていないか)、sshd_configの設定などを確認しておく事
スキャン対象ホストの追加
- スキャン対象のホストを追加する場合は、config.tomlに設定を追加する
(vulsuserで実行) # cd $HOME/vuls_config # vi config.toml 以下フォーマットで設定を追加 [servers.ホスト名] host = "IPアドレス" keyPath = "/home/vulsuser/.ssh/account-xxx/xxx_id_rsa" ・ホストの設定を追記する場所は、アカウント毎にまとめておく事 ・秘密鍵は対象ホストが稼働しているアカウントのものを指定する事 スキャン対象がコンテナ(Docker .etc)の場合は、以下を更に追記 [servers.ホスト名.containers] includes = ["${running}"] ・この設定の場合は、稼働中のコンテナ全てをスキャン対象とする ・その他記載方法や設定については、公式を参照する事 [ https://github.com/future-architect/vuls ] コンフィグ設定が完了したら、configtestを実行しておく事 # cd $HOME # vuls configtest -config=vuls_config/config.toml 追加したホスト名 ex) vuls configtest -config=vuls_config/config.toml server01 エラーが出力されなければOK
以上が、脆弱性スキャン実行環境です。
問題無ければ、毎週月曜日に複数アカウントにまたがった数百のホストをスキャンし、結果をVulsRepo上で俯瞰して確認する事ができます。
バージョンアップやら運用改善で変わっていく個所もありますが、参考にして頂ければと。
次回はconfig設定の記述内容を紹介します。
野村昌男
インフラとセキュリティメインでやっています。
L4/L3以下が好きです。