Skip to content

Latest commit

 

History

History
1354 lines (1060 loc) · 42.5 KB

README.ja.md

File metadata and controls

1354 lines (1060 loc) · 42.5 KB

Vuls: VULnerability Scanner

Slack

Vuls-logo

Vulnerability scanner for Linux/FreeBSD, agentless, written in golang.

README in English
Slackチームはこちらから参加できます。(日本語でオッケーです)

asciicast

Vuls-slack


Abstract

毎日のように発見される脆弱性の調査やソフトウェアアップデート作業は、システム管理者にとって負荷の高いタスクである。 プロダクション環境ではサービス停止リスクを避けるために、パッケージマネージャの自動更新機能を使わずに手動更新で運用するケースも多い。 だが、手動更新での運用には以下の問題がある。

  • システム管理者がNVDなどで新着の脆弱性をウォッチし続けなければならない
  • サーバにインストールされているソフトウェアは膨大であり、システム管理者が全てを把握するのは困難
  • 新着の脆弱性がどのサーバに該当するのかといった調査コストが大きく、漏れる可能性がある

Vulsは上に挙げた手動運用での課題を解決するツールであり、以下の特徴がある。

  • システムに関係ある脆弱性のみ教えてくれる
  • その脆弱性に該当するサーバを教えてくれる
  • 自動スキャンのため脆弱性検知の漏れを防ぐことができる
  • CRONなどで定期実行、レポートすることで脆弱性の放置を防ぐことできる

Vuls-Motivation


Main Features

  • Linuxサーバに存在する脆弱性をスキャン
    • Ubuntu, Debian, CentOS, Amazon Linux, RHELに対応
    • クラウド、オンプレミス、Docker
  • OSパッケージ管理対象外のミドルウェアをスキャン
    • プログラミング言語のライブラリやフレームワーク、ミドルウェアの脆弱性スキャン
    • CPEに登録されているソフトウェアが対象
  • エージェントレスアーキテクチャ
    • スキャン対象サーバにSSH接続可能なマシン1台にセットアップするだけで動作
  • 非破壊スキャン(SSHでコマンド発行するだけ)
  • AWSでの脆弱性/侵入テスト事前申請は必要なし
  • 設定ファイルのテンプレート自動生成
    • CIDRを指定してサーバを自動検出、設定ファイルのテンプレートを生成
  • EmailやSlackで通知可能(日本語でのレポートも可能)
  • 付属するTerminal-Based User Interfaceビューアでは、Vim風キーバインドでスキャン結果を参照可能
  • Web UI(VulsRepo)を使えばピボットテーブルのように分析可能

What Vuls Doesn't Do

  • Vulsはソフトウェアアップデートは行わない

Setup Vuls

Vulsのセットアップは以下の3パターンがある


Hello Vuls

本チュートリアルでは、Amazon EC2にVulsをセットアップし、自分に存在する脆弱性をスキャンする方法を説明する。 手順は以下の通り

  1. Amazon Linuxを新規作成
  2. 自分自身にSSH接続できるように設定
  3. 必要なソフトウェアをインストール
  4. go-cve-dictionaryをデプロイ
  5. Vulsをデプロイ
  6. 設定
  7. Prepare
  8. Scan
  9. Reporting
  10. TUI(Terminal-Based User Interface)で結果を参照する
  11. Web UI(VulsRepo)で結果を参照する

Step1. Launch Amazon Linux

Step2. SSH setting

ローカルホストにSSH接続できるようにする。

SSHキーペアを作成し、公開鍵をauthorized_keysに追加する。

$ ssh-keygen -t rsa
$ cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
$ chmod 600 ~/.ssh/authorized_keys

VulsはSSHパスワード認証をサポートしていない。SSH公開鍵鍵認証を使う必要がある。 また、パスワードありのSUDOもセキュリティ上の理由によりサポートしていないため、スキャン対象サーバに/etc/sudoersにNOPASSWDを設定して、パスワードなしでSUDO可能にする必要がある。

Step3. Install requirements

Vulsセットアップに必要な以下のソフトウェアをインストールする。

$ ssh [email protected]  -i ~/.ssh/private.pem
$ sudo yum -y install sqlite git gcc
$ wget https://storage.googleapis.com/golang/go1.7.1.linux-amd64.tar.gz
$ sudo tar -C /usr/local -xzf go1.7.1.linux-amd64.tar.gz
$ mkdir $HOME/go

/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

Step4. Deploy go-cve-dictionary

$ sudo mkdir /var/log/vuls
$ sudo chown ec2-user /var/log/vuls
$ sudo chmod 700 /var/log/vuls
$
$ 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

バイナリは、$GOPATH/binいかに生成される

NVDから脆弱性データベースを取得する。
環境によって異なるが、AWS上では10分程度かかる。

$ cd $HOME
$ for i in {2002..2016}; do go-cve-dictionary fetchnvd -years $i; done
... snip ...
$ ls -alh cve.sqlite3
-rw-r--r-- 1 ec2-user ec2-user 7.0M Mar 24 13:20 cve.sqlite3

Step5. Deploy Vuls

新規にターミナルを起動し、先ほど作成したEC2にSSH接続する。

$ 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を既にインストール済みでupdateしたい場合は

$ go get -u github.com/future-architect/vuls

で可能である。

go getでエラーが発生した場合は、以下の点を確認する。

  • Gitのバージョンがv2以降か?
  • Go依存パッケージの問題でgo getに失敗する場合は deploying with glide を試す。

Step6. Config

Vulsの設定ファイルを作成する(TOMLフォーマット) 設定ファイルのチェックを行う

$ cd $HOME
$ cat config.toml
[servers]

[servers.172-31-4-82]
host         = "172.31.4.82"
port        = "22"
user        = "ec2-user"
keyPath     = "/home/ec2-user/.ssh/id_rsa"

$ vuls configtest

Step7. Setting up target servers for Vuls

$ vuls prepare

詳細は Usage: Prepare を参照

Step8. Start Scanning

$ vuls scan
... snip ...

Scan Summary
============
172-31-4-82       amazon 2015.09         94 CVEs      103 updatable packages

Step9. Reporting

View one-line summary

$ vuls report -format-one-line-text -cvedb-path=$PWD/cve.sqlite3

One Line Summary
================
172-31-4-82   Total: 94 (High:19 Medium:54 Low:7 ?:14)        103 updatable packages

View short summary.

$ vuls report -format-short-text -cvedb-path=$PWD/cve.sqlite3

172-31-4-8 (amazon 2015.09)
===========================
Total: 94 (High:19 Medium:54 Low:7 ?:14)        103 updatable packages

CVE-2016-0705   10.0 (High)     Double free vulnerability in the dsa_priv_decode function in
                                crypto/dsa/dsa_ameth.c in OpenSSL 1.0.1 before 1.0.1s and 1.0.2 before 1.0.2g
                                allows remote attackers to cause a denial of service (memory corruption) or
                                possibly have unspecified other impact via a malformed DSA private key.
                                http://www.cvedetails.com/cve/CVE-2016-0705
                                http://people.ubuntu.com/~ubuntu-security/cve/CVE-2016-0705
                                libssl1.0.0-1.0.2f-2ubuntu1 -> libssl1.0.0-1.0.2g-1ubuntu4.5
                                openssl-1.0.2f-2ubuntu1 -> openssl-1.0.2g-1ubuntu4.5

... snip ...

View full report.

$ vuls report -format-full-text -cvedb-path=$PWD/cve.sqlite3

172-31-4-82 (amazon 2015.09)
============================
Total: 94 (High:19 Medium:54 Low:7 ?:14)        103 updatable packages


CVE-2016-0705
-------------
Score           10.0 (High)
Vector          (AV:N/AC:L/Au:N/C:C/I:C/A:C)
Summary         Double free vulnerability in the dsa_priv_decode function in
                crypto/dsa/dsa_ameth.c in OpenSSL 1.0.1 before 1.0.1s and 1.0.2 before 1.0.2g
                allows remote attackers to cause a denial of service (memory corruption) or
                possibly have unspecified other impact via a malformed DSA private key.
CWE             https://cwe.mitre.org/data/definitions/.html
NVD             https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2016-0705
MITRE           https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-0705
CVE Details     http://www.cvedetails.com/cve/CVE-2016-0705
CVSS Claculator https://nvd.nist.gov/cvss/v2-calculator?name=CVE-2016-0705&vector=(AV:N/AC:L/...
Ubuntu-CVE      http://people.ubuntu.com/~ubuntu-security/cve/CVE-2016-0705
Package         libssl1.0.0-1.0.2f-2ubuntu1 -> libssl1.0.0-1.0.2g-1ubuntu4.5
                openssl-1.0.2f-2ubuntu1 -> openssl-1.0.2g-1ubuntu4.5

... snip ...

Step10. TUI

Vulsにはスキャン結果の詳細を参照できるイカしたTUI(Terminal-Based User Interface)が付属している。

$ vuls tui

Vuls-TUI

Step11. Web UI

VulsRepoはスキャン結果をビボットテーブルのように分析可能にするWeb UIである。
Online Demoがあるので試してみて。


Architecture

A. Scan via SSH Mode

Vuls-Architecture

B. Scan without SSH (Local Scan Mode)

Vulsをスキャン対象サーバにデプロイする。Vulsはローカルホストにコマンドを発行する(SSH経由ではない)。スキャン結果のJSONを別サーバに集約する。スキャン結果の詳細化のためにはCVEデータベースへのアクセスが必要なので、事前にgo-cve-dictionaryをserver modeで起動しておく。 その集約サーバ上で、あなたはWebUIやTUIを用いて各スキャン対象サーバのスキャン結果を参照することが可能。

Vuls-Architecture Local Scan Mode 詳細

  • NVDとJVN(日本語)から脆弱性データベースを取得し、SQLite3に格納する。

Vuls

Vuls-Scan-Flow

  • SSHでサーバに存在する脆弱性をスキャンし、CVE IDのリストを作成する
    • Dockerコンテナのスキャンする場合、VulsはまずDockerホストにSSHで接続する。その後、Dockerホスト上で docker exec 経由でコマンドを実効する。Dockerコンテナ内にSSHデーモンを起動する必要はない
  • 検出されたCVEの詳細情報をgo-cve-dictionaryから取得する
  • スキャン結果レポートを生成し、SlackやEmailなどで送信する
  • スキャン結果をJSONファイルに出力すると詳細情報をターミナル上で参照可能

Performance Considerations

  • Ubuntu, Debian
    apt-get changelogでアップデート対象のパッケージのチェンジログを取得し、含まれるCVE IDをパースする。 アップデート対象のパッケージが沢山ある場合、チェンジログの取得に時間がかかるので、初回のスキャンは遅い。
    ただ、2回目以降はキャッシュしたchangelogを使うので速くなる。

  • CentOS
    アップデート対象すべてのchangelogを一度で取得しパースする。スキャンスピードは速い、サーバリソース消費量は小さい。

  • Amazon, RHEL and FreeBSD
    高速にスキャンし、スキャン対象サーバのリソース消費量は小さい。

Distribution Scan Speed
Ubuntu 初回は遅い / 2回目以降速い 
Debian 初回は遅い / 2回目以降速い 
CentOS 速い
Amazon 速い
RHEL 速い
FreeBSD 速い

Use Cases

Scan all servers

Vuls-Usecase1

Scan a single server

web/app server in the same configuration under the load balancer

Vuls-Usecase2


Support OS

Distribution Release
Ubuntu 12, 14, 16
Debian 7, 8
RHEL 5, 6, 7
CentOS 5, 6, 7
Amazon Linux All
FreeBSD 10

Usage: Automatic Server Discovery

Discoveryサブコマンドは指定されたCIDRレンジ内でpingが返ってくるサーバを発見して、ターミナル上にVulsの設定ファイルのテンプレートを出力する。

$ vuls discover -help
discover:
        discover 192.168.0.0/24

Example

$ vuls discover 172.31.4.0/24
# Create config.toml using below and then ./vuls --config=/path/to/config.toml

[slack]
hookURL      = "https://hooks.slack.com/services/abc123/defghijklmnopqrstuvwxyz"
channel      = "#channel-name"
#channel      = "${servername}"
iconEmoji    = ":ghost:"
authUser     = "username"
notifyUsers  = ["@username"]

[email]
smtpAddr      = "smtp.gmail.com"
smtpPort      = "587"
user          = "username"
password      = "password"
from          = "[email protected]"
to            = ["[email protected]"]
cc            = ["[email protected]"]
subjectPrefix = "[vuls]"

[default]
#port        = "22"
#user        = "username"
#keyPath     = "/home/username/.ssh/id_rsa"
#cpeNames = [
#  "cpe:/a:rubyonrails:ruby_on_rails:4.2.1",
#]
#containers = ["${running}"]
#optional = [
#    ["key", "value"],
#]

[servers]

[servers.172-31-4-82]
host         = "172.31.4.82"
#port        = "22"
#user        = "root"
#keyPath     = "/home/username/.ssh/id_rsa"
#cpeNames = [
#  "cpe:/a:rubyonrails:ruby_on_rails:4.2.1",
#]
#containers = ["${running}"]
#optional = [
#    ["key", "value"],
#]

このテンプレート使ってVulsの設定ファイルを作ってもよい。


Configuration

  • Slack section

    [slack]
    hookURL      = "https://hooks.slack.com/services/abc123/defghijklmnopqrstuvwxyz"
    channel      = "#channel-name"
    #channel      = "${servername}"
    iconEmoji    = ":ghost:"
    authUser     = "username"
    notifyUsers  = ["@username"]
    
    • hookURL : Incoming webhook's URL

    • channel : channel name.
      channelに${servername}を指定すると、結果レポートをサーバごとに別チャネルにすることが出来る。 以下のサンプルでは、#server1チャネルと#server2チャネルに送信される。スキャン前にチャネルを作成する必要がある。

      [slack]
      channel      = "${servername}"
      ...snip...
      
      [servers]
      
      [servers.server1]
      host         = "172.31.4.82"
      ...snip...
      
      [servers.server2]
      host         = "172.31.4.83"
      ...snip...
      
    • iconEmoji: emoji

    • authUser: username of the slack team

    • notifyUsers: ここにユーザ名を指定すると、Slackで通知を受け取ることができる。たとえば ["@foo", "@bar"]を指定すると、Slackのテキストに@foo@barが含まれるのでスマホなどにPush通知が可能。

  • Mail section

    [email]
    smtpAddr      = "smtp.gmail.com"
    smtpPort      = "587"
    user          = "username"
    password      = "password"
    from          = "[email protected]"
    to            = ["[email protected]"]
    cc            = ["[email protected]"]
    subjectPrefix = "[vuls]"
    
  • Default section

    [default]
    #port        = "22"
    #user        = "username"
    #keyPath     = "/home/username/.ssh/id_rsa"
    #cpeNames = [
    #  "cpe:/a:rubyonrails:ruby_on_rails:4.2.1",
    #]
    #containers = ["${running}"]
    #ignoreCves = ["CVE-2016-6313"]
    #optional = [
    #    ["key", "value"],
    #]
    

    下記serversセクションで値が指定されなかった場合のデフォルト値

  • servers section

    [servers]
    
    [servers.172-31-4-82]
    host         = "172.31.4.82"
    #port        = "22"
    #user        = "root"
    #keyPath     = "/home/username/.ssh/id_rsa"
    #cpeNames = [
    #  "cpe:/a:rubyonrails:ruby_on_rails:4.2.1",
    #]
    #ignoreCves = ["CVE-2016-6314"]
    #optional = [
    #    ["key", "value"],
    #]
    #containers = ["${running}"]
    #[servers.172-31-4-82.container]
    #type = "lxd"
    

    serversセクションの値は、defaultセクションの値よりも優先される。 defaultセクションの値を使いたい場合は # でコメントアウトする。

    Vulsは各サーバにSSHで接続するが、Goのネイティブ実装と、OSコマンドの2種類のSSH接続方法をサポートしている。 詳細は -ssh-external option を参照。

    また、以下のSSH認証をサポートしている。

    • SSH agent
    • SSH public key authentication (with password, empty password) SSH Password認証はサポートしていない

Usage: Configtest

configtestサブコマンドは、config.tomlで定義されたサーバ/コンテナに対してSSH可能かどうかをチェックする。

$ vuls configtest --help
configtest:
        configtest
                        [-config=/path/to/config.toml]
                        [-log-dir=/path/to/log]
                        [-ask-key-password]
                        [-ssh-external]
                        [-debug]

                        [SERVER]...
  -ask-key-password
        Ask ssh privatekey password before scanning
  -config string
        /path/to/toml (default "/Users/kotakanbe/go/src/github.com/future-architect/vuls/config.toml")
  -debug
        debug mode
  -log-dir string
        /path/to/log (default "/var/log/vuls")
  -ssh-external
        Use external ssh command. Default: Use the Go native implementation

また、スキャン対象サーバに対してパスワードなしでSUDO可能な状態かもチェックする。

スキャン対象サーバ上の/etc/sudoersのサンプル

  • CentOS, RHEL, Amazon Linux (CentOS 5の場合は/bin/echoも必要)
vuls ALL=(root) NOPASSWD: /usr/bin/yum (, /bin/echo)
  • Ubuntu, Debian
vuls ALL=(root) NOPASSWD: /usr/bin/apt-get, /usr/bin/apt-cache
  • Amazon Linux, FreeBSDはRoot権限なしでスキャン可能

Usage: Prepare

Prepareサブコマンドは、Vuls内部で利用する以下のパッケージをスキャン対象サーバにインストールする。

Distribution Release Requirements
Ubuntu 12, 14, 16 -
Debian 7, 8 aptitude
CentOS 5 yum-changelog
CentOS 6, 7 yum-plugin-changelog
Amazon All -
RHEL 5, 6, 7 -
FreeBSD 10 -
$ vuls prepare -help
prepare:
        prepare
                        [-config=/path/to/config.toml]
                        [-log-dir=/path/to/log]
                        [-ask-key-password]
                        [-debug]
                        [-ssh-external]

                        [SERVER]...
  -ask-key-password
        Ask ssh privatekey password before scanning
  -config string
        /path/to/toml (default "$PWD/config.toml")
  -debug
        debug mode
  -log-dir string
        /path/to/log (default "/var/log/vuls")
  -ssh-external
        Use external ssh command. Default: Use the Go native implementation

Usage: Scan

$ vuls scan -help
scan:
        scan
                [-config=/path/to/config.toml]
                [-results-dir=/path/to/results]
                [-log-dir=/path/to/log]
                [-cachedb-path=/path/to/cache.db]
                [-ssh-external]
                [-containers-only]
                [-skip-broken]
                [-http-proxy=http://192.168.0.1:8080]
                [-ask-key-password]
                [-debug]
                [-pipe]

                [SERVER]...
  -ask-key-password
        Ask ssh privatekey password before scanning
  -cachedb-path string
        /path/to/cache.db (local cache of changelog for Ubuntu/Debian)
  -config string
        /path/to/toml
  -containers-only
        Scan containers only. Default: Scan both of hosts and containers
  -debug
        debug mode
  -http-proxy string
        http://proxy-url:port (default: empty)
  -log-dir string
        /path/to/log (default "/var/log/vuls")
  -pipe
        Use stdin via PIPE
  -results-dir string
        /path/to/results
  -skip-broken
        [For CentOS] yum update changelog with --skip-broken option
  -ssh-external
        Use external ssh command. Default: Use the Go native implementation

-ssh-external option

Vulsは2種類のSSH接続方法をサポートしている。

デフォルトでは、Goのネイティブ実装 (crypto/ssh) を使ってスキャンする。 これは、SSHコマンドがインストールされていない環境でも動作する(Windowsなど)

外部SSHコマンドを使ってスキャンするためには、-ssh-externalを指定する。 SSH Configが使えるので、ProxyCommandを使った多段SSHなどが可能。
CentOSでは、スキャン対象サーバの/etc/sudoersに以下を追加する必要がある(user: vuls)

Defaults:vuls !requiretty

-ask-key-password option

SSH key password -ask-key-password
empty password -
with password required or use ssh-agent

Example: Scan all servers defined in config file

$ vuls scan -ask-key-password

この例では、

  • SSH公開鍵認証(秘密鍵パスフレーズ)を指定
  • configに定義された全サーバをスキャン

Example: Scan specific servers

$ vuls scan server1 server2

この例では、

  • SSH公開鍵認証(秘密鍵パスフレーズなし)
  • ノーパスワードでsudoが実行可能
  • configで定義されているサーバの中の、server1, server2のみスキャン

Example: Scan via shell instead of SSH.

ローカルホストのスキャンする場合、SSHではなく直接コマンドの発行が可能。
config.tomlのhostにlocalhost または 127.0.0.1かつ、portにlocalを設定する必要がある。
For more details, see Architecture section

  • config.toml
    [servers]
    
    [servers.localhost]
    host         = "localhost" # or "127.0.0.1"
    port         = "local"
    

Example: Scan containers (Docker/LXD)

コンテナはSSHデーモンを起動しないで運用するケースが一般的。
Docker Blog:Why you don't need to run SSHd in your Docker containers

Docker

Vulsは、DockerホストにSSHで接続し、docker execでDockerコンテナにコマンドを発行して脆弱性をスキャンする。
詳細は、Architecture sectionを参照

  • 全ての起動中のDockerコンテナをスキャン
    "${running}" をcontainersに指定する

    [servers]
    
    [servers.172-31-4-82]
    host         = "172.31.4.82"
    user        = "ec2-user"
    keyPath     = "/home/username/.ssh/id_rsa"
    containers = ["${running}"]
    
  • あるコンテナのみスキャン
    コンテナID、または、コンテナ名を、containersに指定する。
    以下の例では、container_name_aと、4aa37a8b63b9のコンテナのみスキャンする
    スキャン実行前に、コンテナが起動中か確認すること。もし起動してない場合はエラーメッセージを出力してスキャンを中断する。

    [servers]
    
    [servers.172-31-4-82]
    host         = "172.31.4.82"
    user        = "ec2-user"
    keyPath     = "/home/username/.ssh/id_rsa"
    containers = ["container_name_a", "4aa37a8b63b9"]
    
  • コンテナのみをスキャンする場合(ホストはスキャンしない)
    --containers-onlyオプションを指定する

LXDコンテナをスキャンする場合

Vulsは、ホストにSSHで接続し、lxc execでLXDコンテナにコマンドを発行して脆弱性をスキャンする。

[servers]

[servers.172-31-4-82]
host         = "172.31.4.82"
user        = "ec2-user"
keyPath     = "/home/username/.ssh/id_rsa"
containers = ["${running}"]
[servers.172-31-4-82.container]
type = "lxd"

Usage: Report

report:
        report
                [-lang=en|ja]
                [-config=/path/to/config.toml]
                [-results-dir=/path/to/results]
                [-log-dir=/path/to/log]
                [-refresh-cve]
                [-cvedb-type=sqlite3|mysql]
                [-cvedb-path=/path/to/cve.sqlite3]
                [-cvedb-url=http://127.0.0.1:1323 or mysql connection string]
                [-cvss-over=7]
                [-ignore-unscored-cves]
                [-to-email]
                [-to-slack]
                [-to-localfile]
                [-to-s3]
                [-to-azure-blob]
                [-format-json]
                [-format-xml]
                [-format-one-line-text]
                [-format-short-text]
                [-format-full-text]
                [-gzip]
                [-aws-profile=default]
                [-aws-region=us-west-2]
                [-aws-s3-bucket=bucket_name]
                [-azure-account=accout]
                [-azure-key=key]
                [-azure-container=container]
                [-http-proxy=http://192.168.0.1:8080]
                [-debug]
                [-debug-sql]
                [-pipe]

                [SERVER]...
  -aws-profile string
        AWS profile to use (default "default")
  -aws-region string
        AWS region to use (default "us-east-1")
  -aws-s3-bucket string
        S3 bucket name
  -azure-account string
        Azure account name to use. AZURE_STORAGE_ACCOUNT environment variable is used if not specified
  -azure-container string
        Azure storage container name
  -azure-key string
        Azure account key to use. AZURE_STORAGE_ACCESS_KEY environment variable is used if not specified
  -config string
        /path/to/toml
  -cvedb-path string
        /path/to/sqlite3 (For get cve detail from cve.sqlite3)
  -cvedb-type string
        DB type for fetching CVE dictionary (sqlite3 or mysql) (default "sqlite3")
  -cvedb-url string
        http://cve-dictionary.com:8080 or mysql connection string
  -cvss-over float
        -cvss-over=6.5 means reporting CVSS Score 6.5 and over (default: 0 (means report all))
  -debug
        debug mode
  -debug-sql
        SQL debug mode
  -format-full-text
        Detail report in plain text
  -format-json
        JSON format
  -format-one-line-text
        One line summary in plain text
  -format-short-text
        Summary in plain text
  -format-xml
        XML format
  -gzip
        gzip compression
  -http-proxy string
        http://proxy-url:port (default: empty)
  -ignore-unscored-cves
        Don't report the unscored CVEs
  -lang string
        [en|ja] (default "en")
  -log-dir string
        /path/to/log (default "/var/log/vuls")
  -pipe
        Use stdin via PIPE
  -refresh-cve
        Refresh CVE information in JSON file under results dir
  -results-dir string
        /path/to/results
  -to-azure-blob
        Write report to Azure Storage blob (container/yyyyMMdd_HHmm/servername.json/xml/txt)
  -to-email
        Send report via Email
  -to-localfile
        Write report to localfile
  -to-s3
        Write report to S3 (bucket/yyyyMMdd_HHmm/servername.json/xml/txt)
  -to-slack
        Send report via Slack

Example: Send scan results to Slack

$ vuls report \
      -to-slack \
      -cvss-over=7 \
      -cvedb-path=$PWD/cve.sqlite3

With this sample command, it will ..

  • Slack通知
  • CVSS score が 7.0以上のもののみ通知

Example: Put results in S3 bucket

事前にAWS関連の設定を行う

$ vuls scan \
      -cvedb-path=$PWD/cve.sqlite3 \
      -to-s3 \
      -format-json \
      -aws-region=ap-northeast-1 \
      -aws-s3-bucket=vuls \
      -aws-profile=default

この例では、

  • 結果をJSON形式でS3に格納する。
    • バケット名 ... vuls
    • リージョン ... ap-northeast-1
    • 利用するProfile ... default

Example: Put results in Azure Blob storage

事前にAzure Blob関連の設定を行う

  • Azure Blob Containerを作成
$ vuls scan \
      -cvedb-path=$PWD/cve.sqlite3 \
      -to-azure-blob \
      -format-xml \
      -azure-container=vuls \
      -azure-account=test \
      -azure-key=access-key-string

この例では、

  • 結果をXML形式でBlobに格納する。
    • コンテナ名 ... vuls
    • ストレージアカウント名 ... test
    • アクセスキー ... access-key-string

また、アカウント名とアクセスキーは環境変数でも定義が可能

$ export AZURE_STORAGE_ACCOUNT=test
$ export AZURE_STORAGE_ACCESS_KEY=access-key-string
$ vuls scan \
      -cve-dictionary-dbpath=$PWD/cve.sqlite3 \
      -report-azure-blob \
      -azure-container=vuls

Example: IgnoreCves

Slack, EMail, テキスト出力しないくないCVE IDがある場合は、設定ファイルに定義することでレポートされなくなる。 ただ、JSONファイルには以下のように出力される。

  • config.toml
[default]
ignoreCves = ["CVE-2016-6313"]

[servers.bsd]
host     = "192.168.11.11"
user     = "kanbe"
ignoreCves = ["CVE-2016-6314"]
  • bsd.json
[
  {
    "ServerName": "bsd",
    "Family": "FreeBSD",
    "Release": "10.3-RELEASE",
    "IgnoredCves" : [
      "CveDetail" : {
        "CVE-2016-6313",
        ...
      },
      "CveDetail" : {
        "CVE-2016-6314",
        ...
      }
    ]
  }
]

Example: Add optional key-value pairs to JSON

追加情報をJSONに含めることができる。
デフォルトセクションのkey-valueはserversセクションのもので上書きされる。
使い方の例として、AzureリソースグループやVM名を指定しておくことで、結果のJSONをスクリプトでパースしてAzure VMの操作をする、などが可能。

  • config.toml
[default]
optional = [
	["key1", "default_value"],
	["key3", "val3"],
]

[servers.bsd]
host     = "192.168.11.11"
user     = "kanbe"
optional = [
	["key1", "val1"],
	["key2", "val2"],
]
  • bsd.json
[
  {
    "ServerName": "bsd",
    "Family": "FreeBSD",
    "Release": "10.3-RELEASE",
    .... snip ...
    "Optional": [
      [  "key1", "val1" ],
      [  "key2", "val2" ],
      [  "key3", "val3" ]
    ]
  }
]

Example: Use MySQL as a DB storage back-end

$ vuls scan \
      -cve-dictionary-dbtype=mysql \
      -cve-dictionary-dbpath="user:pass@tcp(localhost:3306)/dbname?parseTime=true"

Usage: Scan vulnerability of non-OS package

Vulsは、CPEに登録されているソフトウェアであれば、OSパッケージ以外のソフトウェアの脆弱性もスキャン可能。
たとえば、自分でコンパイルしたものや、言語のライブラリ、フレームワークなど。

  • CPEの検索方法

  • Configuration
    例えば、Ruby on Rails v4.2.1の脆弱性を検知したい場合は、serversセクションに以下のように定義する。

    [servers]
    
    [servers.172-31-4-82]
    host         = "172.31.4.82"
    user        = "ec2-user"
    keyPath     = "/home/username/.ssh/id_rsa"
    cpeNames = [
      "cpe:/a:rubyonrails:ruby_on_rails:4.2.1",
    ]
    

Usage: Integrate with OWASP Dependency Check to Automatic update when the libraries are updated (Experimental)

OWASP Dependency check は、プログラミング言語のライブラリを特定し(CPEを推測)、公開済みの脆弱性を検知するツール。

VulsとDependency Checkを連携させる方法は以下

  • Dependency Checkを、--format=XMLをつけて実行する

  • そのXMLをconfig.toml内で以下のように定義する

    [servers]
    
    [servers.172-31-4-82]
    host         = "172.31.4.82"
    user        = "ec2-user"
    keyPath     = "/home/username/.ssh/id_rsa"
    dependencyCheckXMLPath = "/tmp/dependency-check-report.xml"
    

VulsとDependency Checkの連携すると以下の利点がある

  • ライブラリを更新した場合に、config.tomlのCPEの定義を変更しなくても良い
  • Vulsの機能でSlack, Emailで通知可能
  • 日本語のレポートが可能
    • Dependency Checkは日本語レポートに対応していない

Usage: TUI

Display the latest scan results

$ vuls tui -h
tui:
        tui
                [-cvedb-type=sqlite3|mysql]
                [-cvedb-path=/path/to/cve.sqlite3]
                [-cvedb-url=http://127.0.0.1:1323 or mysql connection string]
                [-results-dir=/path/to/results]
                [-refresh-cve]
                [-debug-sql]
                [-pipe]

  -cvedb-path string
        /path/to/sqlite3 (For get cve detail from cve.sqlite3)
  -cvedb-type string
        DB type for fetching CVE dictionary (sqlite3 or mysql)
  -cvedb-url string
        http://cve-dictionary.com:8080 or mysql connection string
  -debug-sql
        debug SQL
  -pipe
        Use stdin via PIPE
  -refresh-cve
        Refresh CVE information in JSON file under results dir
  -results-dir string
        /path/to/results

Key binding is below.

| key | | |:-----------------|:-------|:------| | TAB | move cursor among the panes | | Arrow up/down | move cursor to up/down | | Ctrl+j, Ctrl+k | move cursor to up/down | | Ctrl+u, Ctrl+d | page up/down |

For details, see https://github.com/future-architect/vuls/blob/master/report/tui.go

Display the previous scan results

  • Display the list of scan results.
$ vuls history
20160524_1950 scanned 1 servers: amazon2
20160524_1940 scanned 2 servers: amazon1, romantic_goldberg
  • Display the result of scan 20160524_1949
$ vuls tui 20160524_1950
  • Display the result of scan 20160524_1948
$ vuls tui 20160524_1940

Display the previous scan results using peco

$ vuls history | peco | vuls tui -pipe

asciicast

Usage: go-cve-dictonary on different server

Run go-cve-dictionary as server mode before scanning on 192.168.10.1

$ go-cve-dictionary server -bind=192.168.10.1 -port=1323

Run Vuls with -cve-dictionary-url option.

$ vuls scan -cve-dictionary-url=http://192.168.0.1:1323

Usage: Update NVD Data

see go-cve-dictionary#usage-fetch-nvd-data


レポートの日本語化

see go-cve-dictionary#usage-fetch-jvn-data

fetchnvd, fetchjvnの実行順序の注意

fetchjvn -> fetchnvdの順番だとすごく時間がかかる (2016年9月現在)
fetchnvd -> fetchjvnの順番で実行すること

$ for i in {2002..2016}; do go-cve-dictionary fetchnvd -years $i; done
$ for i in {1998..2016}; do go-cve-dictionary fetchjvn -years $i; done

の順でやった場合、最初のコマンドが15分程度、二つ目のコマンドが10分程度(環境依存)

$ for i in {1998..2016}; do go-cve-dictionary fetchjvn -years $i; done
$ for i in {2002..2016}; do go-cve-dictionary fetchnvd -years $i; done

の順で行うと、最初のコマンドは1時間くらいで終わるが二つ目のコマンドが21時間かかることもある(環境依存)。

スキャン実行

$ vuls scan -lang=ja

Scan時にlang=jaを指定すると脆弱性レポートが日本語になる
slack, emailは日本語対応済み TUIは日本語表示未対応


Update Vuls With Glide

  • Update go-cve-dictionary
    If the DB schema was changed, please specify new SQLite3 or MySQL DB file.
$ cd $GOPATH/src/github.com/kotakanbe/go-cve-dictionary
$ git pull
$ mv vendor /tmp/foo
$ make install
  • Update vuls
$ cd $GOPATH/src/github.com/future-architect/vuls
$ git pull
$ mv vendor /tmp/bar
$ make install
  • バイナリファイルは$GOPARH/bin以下に作成される

Misc

  • go get時にエラーが出る
    Gitをv2にアップデートしてお試しを
    see https://groups.google.com/forum/#!topic/mgo-users/rO1-gUDFo_g

  • HTTP Proxy サポート プロキシ環境下では、-http-proxyオプションを指定

  • go-cve-dictionaryのデーモン化
    Use Systemd, Upstart or supervisord, daemontools...

  • NVD, JVNの脆弱性データベースの自動更新
    CRONなどを使えば可能

  • 自動定期スキャン
    CRONなどを使い、自動化のためにsudoと、秘密鍵のパスワードなしでも実行可能なようにする

    • スキャン対象サーバの /etc/sudoers に NOPASSWORD を設定する
    • 秘密鍵パスフレーズなしの公開鍵認証か、ssh-agentを使う
  • スキャンが重く感じる
    vulsのスキャン対象に脆弱性が溜まりすぎると実行時間が長くなります 脆弱性のある状態は溜めすぎないようにしましょう

  • クロスコンパイル

    $ cd /path/to/your/local-git-reporsitory/vuls
    $ GOOS=linux GOARCH=amd64 go build -o vuls.amd64
  • Logging
    Log is under /var/log/vuls/

  • Debug
    Run with --debug, --sql-debug option.

  • Adjusting Open File Limit
    Riak docs is awesome.

  • Does Vuls accept ssh connections with fish-shell or old zsh as the login shell?
    No, Vuls needs a user on the server for bash login. see also #8

  • Windows
    Use Microsoft Baseline Security Analyzer. MBSA


Related Projects


Data Source

Authors

kotakanbe (@kotakanbe) created vuls and these fine people have contributed.


Contribute

  1. fork a repository: github.com/future-architect/vuls to github.com/you/repo
  2. get original code: go get github.com/future-architect/vuls
  3. work on original code
  4. add remote to your repo: git remote add myfork https://github.com/you/repo.git
  5. push your changes: git push myfork
  6. create a new Pull Request

Change Log

Please see CHANGELOG.


License

Please see LICENSE.