diff --git a/.gitignore b/.gitignore index d80b0b3bdf..fc852d945b 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,7 @@ vuls .vscode *.txt *.json -*.sqlite3 +*.sqlite3* *.db tags .gitmodules @@ -12,3 +12,4 @@ vendor/ log/ results/ *config.toml +!setup/docker/* diff --git a/ISSUE_TEMPLATE b/ISSUE_TEMPLATE new file mode 100644 index 0000000000..51f9b478f7 --- /dev/null +++ b/ISSUE_TEMPLATE @@ -0,0 +1,36 @@ + +# Environment + +## Vuls + +Hash : ____ + +To check the commit hash of HEAD +$ vuls -v + +or +$ cd $GOPATH/src/github.com/future-architect/vuls +$ git rev-parse --short HEAD + +## OS +- Target Server: Write here +- Vuls Server: Write here + +## Go +- Go version: here + +# Current Output + +Please re-run the command using ```-debug``` and provide the output below. + +# Addition Details + +Can you also please fill in each of the remaining sections. + +## Expected Behavior + +## Actual Behavior + +## Steps to reproduce the behaviour + + diff --git a/Makefile b/Makefile index d29699d7cf..702e6dcb04 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,9 @@ .PHONY: \ + glide \ + deps \ + update \ + build \ + install \ all \ vendor \ lint \ @@ -12,12 +17,27 @@ SRCS = $(shell git ls-files '*.go') PKGS = ./. ./config ./models ./report ./cveapi ./scan ./util ./commands ./cache +VERSION := $(shell git describe --tags --abbrev=0) +REVISION := $(shell git rev-parse --short HEAD) +LDFLAGS := -X 'main.version=$(VERSION)' \ + -X 'main.revision=$(REVISION)' -all: test +glide: + go get github.com/Masterminds/glide + +deps: glide + glide install + +update: glide + glide update -# vendor: -# @ go get -v github.com/mjibson/party -# party -d external -c -u +build: main.go deps + go build -ldflags "$(LDFLAGS)" -o vuls $< + +install: main.go deps + go install -ldflags "$(LDFLAGS)" + +all: test lint: @ go get -v github.com/golang/lint/golint diff --git a/README.fr.md b/README.fr.md index e8ae519fd8..69a34e6c41 100644 --- a/README.fr.md +++ b/README.fr.md @@ -107,14 +107,14 @@ Vuls requiert l'installation des paquets suivants : - sqlite - git - gcc -- go v1.6 +- go v1.7.1 or later - https://golang.org/doc/install ```bash $ ssh ec2-user@52.100.100.100 -i ~/.ssh/private.pem $ sudo yum -y install sqlite git gcc -$ wget https://storage.googleapis.com/golang/go1.6.linux-amd64.tar.gz -$ sudo tar -C /usr/local -xzf go1.6.linux-amd64.tar.gz +$ 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 ``` Ajoutez les lignes suivantes dans /etc/profile.d/goenv.sh @@ -201,7 +201,7 @@ Summary Unspecified vulnerability in the Java SE and Java SE Embedded co NVD https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2016-0494 MITRE https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-0494 CVE Details http://www.cvedetails.com/cve/CVE-2016-0494 -CVSS Claculator https://nvd.nist.gov/cvss/v2-calculator?name=CVE-2016-0494&vector=(AV:N/AC:L/Au:N/C:C/I:C/A:C) +CVSS Calculator https://nvd.nist.gov/cvss/v2-calculator?name=CVE-2016-0494&vector=(AV:N/AC:L/Au:N/C:C/I:C/A:C) RHEL-CVE https://access.redhat.com/security/cve/CVE-2016-0494 ALAS-2016-643 https://alas.aws.amazon.com/ALAS-2016-643.html Package/CPE java-1.7.0-openjdk-1.7.0.91-2.6.2.2.63.amzn1 -> java-1.7.0-openjdk-1:1.7.0.95-2.6.4.0.65.amzn1 diff --git a/README.ja.md b/README.ja.md index 8df0f87a7a..bc4b5da9ff 100644 --- a/README.ja.md +++ b/README.ja.md @@ -46,6 +46,8 @@ Vulsは上に挙げた手動運用での課題を解決するツールであり - CPEに登録されているソフトウェアが対象 - エージェントレスアーキテクチャ - スキャン対象サーバにSSH接続可能なマシン1台にセットアップするだけで動作 +- 非破壊スキャン(SSHでコマンド発行するだけ) +- AWSでの脆弱性/侵入テスト事前申請は必要なし - 設定ファイルのテンプレート自動生成 - CIDRを指定してサーバを自動検出、設定ファイルのテンプレートを生成 - EmailやSlackで通知可能(日本語でのレポートも可能) @@ -65,7 +67,6 @@ Vulsは上に挙げた手動運用での課題を解決するツールであり Vulsのセットアップは以下の3パターンがある - Dockerコンテナ上にセットアップ -Docker Composeを用いて少ないコマンドでセットアップ可能 see https://github.com/future-architect/vuls/tree/master/setup/docker [日本語README](https://github.com/future-architect/vuls/blob/master/setup/docker/README.ja.md) - Chefでセットアップ @@ -121,17 +122,17 @@ VulsはSSHパスワード認証をサポートしていない。SSH公開鍵鍵 Vulsセットアップに必要な以下のソフトウェアをインストールする。 -- SQLite3 -- git v2 +- SQLite3 or MySQL +- git - gcc -- go v1.6 +- go v1.7.1 or later - https://golang.org/doc/install ```bash $ ssh ec2-user@52.100.100.100 -i ~/.ssh/private.pem $ sudo yum -y install sqlite git gcc -$ wget https://storage.googleapis.com/golang/go1.6.linux-amd64.tar.gz -$ sudo tar -C /usr/local -xzf go1.6.linux-amd64.tar.gz +$ 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 を作成し、下記を追加する。 @@ -149,26 +150,19 @@ $ source /etc/profile.d/goenv.sh ## Step4. Deploy [go-cve-dictionary](https://github.com/kotakanbe/go-cve-dictionary) -go get - ```bash $ sudo mkdir /var/log/vuls $ sudo chown ec2-user /var/log/vuls $ sudo chmod 700 /var/log/vuls -$ go get github.com/kotakanbe/go-cve-dictionary +$ +$ mkdir -p $GOPATH/src/github.com/kotakanbe +$ cd $GOPATH/src/github.com/kotakanbe +$ git https://github.com/kotakanbe/go-cve-dictionary.git +$ cd go-cve-dictionary +$ make install ``` +バイナリは、`$GOPATH/bin`いかに生成される -go-cve-dictionaryを既にインストール済みでupdateしたい場合は - -```bash -$ go get -u github.com/kotakanbe/go-cve-dictionary -``` - -で可能である。 - -go getでエラーが発生した場合は、以下の点を確認する。 -- Gitのバージョンがv2以降か? -- Go依存パッケージの問題でgo getに失敗する場合は [deploying with glide](https://github.com/future-architect/vuls/blob/master/README.md#deploy-with-glide) を試す。 NVDから脆弱性データベースを取得する。 環境によって異なるが、AWS上では10分程度かかる。 @@ -183,10 +177,12 @@ $ ls -alh cve.sqlite3 ## Step5. Deploy Vuls 新規にターミナルを起動し、先ほど作成したEC2にSSH接続する。 - -go get ``` -$ go get github.com/future-architect/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 ``` vulsを既にインストール済みでupdateしたい場合は @@ -229,7 +225,7 @@ $ vuls prepare ## Step8. Start Scanning ``` -$ vuls scan -cve-dictionary-dbpath=$PWD/cve.sqlite3 +$ vuls scan -cve-dictionary-dbpath=$PWD/cve.sqlite3 -report-json INFO[0000] Start scanning (config: /home/ec2-user/config.toml) INFO[0000] Start scanning INFO[0000] config: /home/ec2-user/config.toml @@ -256,7 +252,7 @@ Summary Unspecified vulnerability in the Java SE and Java SE Embedded co NVD https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2016-0494 MITRE https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-0494 CVE Details http://www.cvedetails.com/cve/CVE-2016-0494 -CVSS Claculator https://nvd.nist.gov/cvss/v2-calculator?name=CVE-2016-0494&vector=(AV:N/AC:L/Au:N/C:C/I:C/A:C) +CVSS Calculator https://nvd.nist.gov/cvss/v2-calculator?name=CVE-2016-0494&vector=(AV:N/AC:L/Au:N/C:C/I:C/A:C) RHEL-CVE https://access.redhat.com/security/cve/CVE-2016-0494 ALAS-2016-643 https://alas.aws.amazon.com/ALAS-2016-643.html Package/CPE java-1.7.0-openjdk-1.7.0.91-2.6.2.2.63.amzn1 -> java-1.7.0-openjdk-1:1.7.0.95-2.6.4.0.65.amzn1 @@ -375,7 +371,7 @@ notifyUsers = ["@username"] [mail] smtpAddr = "smtp.gmail.com" -smtpPort = "465" +smtpPort = "587" user = "username" password = "password" from = "from@address.com" @@ -428,7 +424,7 @@ host = "172.31.4.82" notifyUsers = ["@username"] ``` - - hookURL : Incomming webhook's URL + - hookURL : Incoming webhook's URL - channel : channel name. channelに`${servername}`を指定すると、結果レポートをサーバごとに別チャネルにすることが出来る。 以下のサンプルでは、`#server1`チャネルと`#server2`チャネルに送信される。スキャン前にチャネルを作成する必要がある。 @@ -456,7 +452,7 @@ host = "172.31.4.82" ``` [mail] smtpAddr = "smtp.gmail.com" - smtpPort = "465" + smtpPort = "587" user = "username" password = "password" from = "from@address.com" @@ -475,6 +471,7 @@ host = "172.31.4.82" # "cpe:/a:rubyonrails:ruby_on_rails:4.2.1", #] #containers = ["${running}"] + #ignoreCves = ["CVE-2016-6313"] #optional = [ # ["key", "value"], #] @@ -494,6 +491,7 @@ host = "172.31.4.82" # "cpe:/a:rubyonrails:ruby_on_rails:4.2.1", #] #containers = ["${running}"] + #ignoreCves = ["CVE-2016-6314"] #optional = [ # ["key", "value"], #] @@ -508,6 +506,7 @@ host = "172.31.4.82" - keyPath: SSH private key path - cpeNames: see [Usage: Scan vulnerability of non-OS package](https://github.com/future-architect/vuls/blob/master/README.ja.md#usage-scan-vulnerability-of-non-os-package) - containers: see [Usage: Scan Docker containers](https://github.com/future-architect/vuls/blob/master/README.ja.md#usage-scan-docker-containers) + - ignoreCves: CVE IDs that will not be reported. But output to JSON file. - optional: JSONレポートに含めたい追加情報 @@ -563,7 +562,7 @@ vuls ALL=(root) NOPASSWD: /usr/bin/apt-get, /usr/bin/apt-cache # Usage: Prepare -Prepareサブコマンドは、Vuls内部で利用する以下のパッケージをスキャン対象サーバにインストーする。 +Prepareサブコマンドは、Vuls内部で利用する以下のパッケージをスキャン対象サーバにインストールする。 | Distribution| Release | Requirements | |:------------|-------------------:|:-------------| @@ -578,17 +577,22 @@ Prepareサブコマンドは、Vuls内部で利用する以下のパッケージ ``` $ vuls prepare -help -prepare - [-config=/path/to/config.toml] [-debug] +prepare: + prepare + [-config=/path/to/config.toml] [-ask-key-password] - [SERVER]... + [-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 + -ssh-external + Use external ssh command. Default: Use the Go native implementation ``` ---- @@ -602,7 +606,8 @@ scan: [-lang=en|ja] [-config=/path/to/config.toml] [-results-dir=/path/to/results] - [-cve-dictionary-dbpath=/path/to/cve.sqlite3] + [-cve-dictionary-dbtype=sqlite3|mysql] + [-cve-dictionary-dbpath=/path/to/cve.sqlite3 or mysql connection string] [-cve-dictionary-url=http://127.0.0.1:1323] [-cache-dbpath=/path/to/cache.db] [-cvss-over=7] @@ -649,7 +654,9 @@ scan: -containers-only Scan concontainers Only. Default: Scan both of hosts and containers -cve-dictionary-dbpath string - /path/to/sqlite3 (For get cve detail from cve.sqlite3) + /path/to/sqlite3 (For get cve detail from cve.sqlite3) + -cve-dictionary-dbtype string + DB type for fetching CVE dictionary (sqlite3 or mysql) (default "sqlite3") -cve-dictionary-url string http://CVE.Dictionary (default "http://127.0.0.1:1323") -cvss-over float @@ -788,6 +795,43 @@ $ vuls scan \ -azure-container=vuls ``` +## Example: IgnoreCves + +Slack, Mail, テキスト出力しないくないCVE IDがある場合は、設定ファイルに定義することでレポートされなくなる。 +ただ、JSONファイルには以下のように出力される。 + +- config.toml +```toml +[default] +ignoreCves = ["CVE-2016-6313"] + +[servers.bsd] +host = "192.168.11.11" +user = "kanbe" +ignoreCves = ["CVE-2016-6314"] +``` + +- bsd.json +```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に含めることができる。 @@ -828,6 +872,14 @@ optional = [ ] ``` +## 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 @@ -855,6 +907,31 @@ Vulsは、[CPE](https://nvd.nist.gov/cpe.cfm)に登録されているソフト "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](https://www.owasp.org/index.php/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: Scan Docker containers @@ -909,14 +986,14 @@ tui: ``` -Key binding is bellow. +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/donw | -| Ctrl+u, Ctrl+d | page up/donw | +| 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 @@ -962,89 +1039,14 @@ $ vuls scan -cve-dictionary-url=http://192.168.0.1:1323 # Usage: Update NVD Data -``` -$ go-cve-dictionary fetchnvd -h -fetchnvd: - fetchnvd - [-last2y] - [-dbpath=/path/to/cve.sqlite3] - [-debug] - [-debug-sql] - - -dbpath string - /path/to/sqlite3 (default "$PWD/cve.sqlite3") - -debug - debug mode - -debug-sql - SQL debug mode - -last2y - Refresh NVD data in the last two years. -``` - -- Fetch data of the entire period - -``` -$ for i in {2002..2016}; do go-cve-dictionary fetchnvd -years $i; done -``` - -- Fetch data in the last 2 years - -``` -$ go-cve-dictionary fetchnvd -last2y -``` +see [go-cve-dictionary#usage-fetch-nvd-data](https://github.com/kotakanbe/go-cve-dictionary#usage-fetch-nvd-data) ---- # レポートの日本語化 -- JVNから日本語の脆弱性情報を取得 - ``` - $ go-cve-dictionary fetchjvn -h - fetchjvn: - fetchjvn - [-latest] - [-last2y] - [-years] 1998 1999 ... - [-dbpath=$PWD/cve.sqlite3] - [-http-proxy=http://192.168.0.1:8080] - [-debug] - [-debug-sql] - - -dbpath string - /path/to/sqlite3 (default "$PWD/cve.sqlite3") - -debug - debug mode - -debug-sql - SQL debug mode - -http-proxy string - http://proxy-url:port (default: empty) - -last2y - Refresh JVN data in the last two years. - -latest - Refresh JVN data for latest. - -years - Refresh JVN data of specific years. +see [go-cve-dictionary#usage-fetch-jvn-data](https://github.com/kotakanbe/go-cve-dictionary#usage-fetch-jvn-data) - ``` - -- すべての期間の脆弱性情報を取得(10分未満) - ``` - $ for i in {1998..2016}; do ./go-cve-dictionary fetchjvn -years $i; done - ``` - -- 2年分の情報を取得 - ``` - $ go-cve-dictionary fetchjvn -last2y - ``` - -- 最新情報のみ取得 - ``` - $ go-cve-dictionary fetchjvn -latest - ``` - -- 脆弱性情報の自動アップデート -Cronなどのジョブスケジューラを用いて実現可能。 --latestオプションを指定して夜間の日次実行を推奨。 ## fetchnvd, fetchjvnの実行順序の注意 @@ -1075,45 +1077,23 @@ slack, emailは日本語対応済み TUIは日本語表示未対応 ---- -# Deploy With Glide - -If an error occurred while go get, try deploying with glide. -- Install [Glide](https://github.com/Masterminds/glide) -- Deploy go-cve-dictionary -``` -$ go get -d github.com/kotakanbe/go-cve-dictionary -$ cd $GOPATH/src/github.com/kotakanbe/go-cve-dictionary -$ glide install -$ go install -``` -- Deploy vuls -``` -$ go get -d github.com/future-architect/vuls -$ cd $GOPATH/src/github.com/future-architect/vuls -$ glide install -$ go install -``` -- The binaries are created under $GOPARH/bin - ----- - # Update Vuls With Glide - Update go-cve-dictionary -If the DB schema was changed, please specify new SQLite3 DB file. +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 -$ glide install -$ go install +$ mv vendor /tmp/foo +$ make install ``` - Update vuls ``` $ cd $GOPATH/src/github.com/future-architect/vuls $ git pull -$ glide install -$ go install +$ mv vendor /tmp/bar +$ make install ``` - バイナリファイルは`$GOPARH/bin`以下に作成される @@ -1210,7 +1190,7 @@ Please see [CHANGELOG](https://github.com/future-architect/vuls/blob/master/CHAN ---- -# Licence +# License Please see [LICENSE](https://github.com/future-architect/vuls/blob/master/LICENSE). diff --git a/README.md b/README.md index d1e5819cdc..75eb206561 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,8 @@ Vuls is a tool created to solve the problems listed above. It has the following - Support software registered in CPE - Agentless architecture - User is required to only setup one machine that is connected to other target servers via SSH +- Nondestructive testing +- Pre-authorization is not necessary before scanning on AWS - Auto generation of configuration file template - Auto detection of servers set using CIDR, generate configuration file template - Email and Slack notification is possible (supports Japanese language) @@ -128,17 +130,17 @@ And also, SUDO with password is not supported for security reasons. So you have Vuls requires the following packages. -- SQLite3 -- git v2 +- SQLite3 or MySQL +- git - gcc -- go v1.6 +- go v1.7.1 or later - https://golang.org/doc/install ```bash $ ssh ec2-user@52.100.100.100 -i ~/.ssh/private.pem $ sudo yum -y install sqlite git gcc -$ wget https://storage.googleapis.com/golang/go1.6.linux-amd64.tar.gz -$ sudo tar -C /usr/local -xzf go1.6.linux-amd64.tar.gz +$ 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 ``` Add these lines into /etc/profile.d/goenv.sh @@ -156,18 +158,18 @@ $ source /etc/profile.d/goenv.sh ## Step4. Deploy [go-cve-dictionary](https://github.com/kotakanbe/go-cve-dictionary) -go get - ```bash $ sudo mkdir /var/log/vuls $ sudo chown ec2-user /var/log/vuls $ sudo chmod 700 /var/log/vuls -$ go get github.com/kotakanbe/go-cve-dictionary +$ +$ 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 ``` - -If an error occurred while go get, check the following points. -- Update Git -- try [deploying with glide](https://github.com/future-architect/vuls/blob/master/README.md#deploy-with-glide). +The binary was built under `$GOPARH/bin` Fetch vulnerability data from NVD. It takes about 10 minutes (on AWS). @@ -183,14 +185,14 @@ $ ls -alh cve.sqlite3 Launch a new terminal and SSH to the ec2 instance. -go get ``` -$ go get github.com/future-architect/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 ``` - -If an error occurred while go get, check the following points. -- Update Git -- try [deploying with glide](https://github.com/future-architect/vuls/blob/master/README.md#deploy-with-glide). +The binary was built under `$GOPARH/bin` ## Step6. Config @@ -220,7 +222,7 @@ see [Usage: Prepare](https://github.com/future-architect/vuls#usage-prepare) ## Step8. Start Scanning ``` -$ vuls scan -cve-dictionary-dbpath=$PWD/cve.sqlite3 +$ vuls scan -cve-dictionary-dbpath=$PWD/cve.sqlite3 -report-json INFO[0000] Start scanning (config: /home/ec2-user/config.toml) INFO[0000] Start scanning INFO[0000] config: /home/ec2-user/config.toml @@ -247,7 +249,7 @@ Summary Unspecified vulnerability in the Java SE and Java SE Embedded co NVD https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2016-0494 MITRE https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-0494 CVE Details http://www.cvedetails.com/cve/CVE-2016-0494 -CVSS Claculator https://nvd.nist.gov/cvss/v2-calculator?name=CVE-2016-0494&vector=(AV:N/AC:L/Au:N/C:C/I:C/A:C) +CVSS Calculator https://nvd.nist.gov/cvss/v2-calculator?name=CVE-2016-0494&vector=(AV:N/AC:L/Au:N/C:C/I:C/A:C) RHEL-CVE https://access.redhat.com/security/cve/CVE-2016-0494 ALAS-2016-643 https://alas.aws.amazon.com/ALAS-2016-643.html Package/CPE java-1.7.0-openjdk-1.7.0.91-2.6.2.2.63.amzn1 -> java-1.7.0-openjdk-1:1.7.0.95-2.6.4.0.65.amzn1 @@ -282,7 +284,7 @@ see https://github.com/future-architect/vuls/tree/master/setup/docker ![Vuls-Architecture](img/vuls-architecture.png) ## [go-cve-dictinary](https://github.com/kotakanbe/go-cve-dictionary) -- Fetch vulnerability information from NVD and JVN(Japanese), then insert into SQLite3. +- Fetch vulnerability information from NVD and JVN(Japanese), then insert into SQLite3 or MySQL. ## Scanning Flow ![Vuls-Scan-Flow](img/vuls-scan-flow.png) @@ -373,7 +375,7 @@ notifyUsers = ["@username"] [mail] smtpAddr = "smtp.gmail.com" -smtpPort = "465" +smtpPort = "587" user = "username" password = "password" from = "from@address.com" @@ -389,6 +391,7 @@ subjectPrefix = "[vuls]" # "cpe:/a:rubyonrails:ruby_on_rails:4.2.1", #] #containers = ["${running}"] +#ignoreCves = ["CVE-2016-6313"] #optional = [ # ["key", "value"], #] @@ -404,6 +407,7 @@ host = "172.31.4.82" # "cpe:/a:rubyonrails:ruby_on_rails:4.2.1", #] #containers = ["${running}"] +#ignoreCves = ["CVE-2016-6313"] #optional = [ # ["key", "value"], #] @@ -426,7 +430,7 @@ You can customize your configuration using this template. notifyUsers = ["@username"] ``` - - hookURL : Incomming webhook's URL + - hookURL : Incoming webhook's URL - channel : channel name. If you set `${servername}` to channel, the report will be sent to each channel. In the following example, the report will be sent to the `#server1` and `#server2`. @@ -457,7 +461,7 @@ You can customize your configuration using this template. ``` [mail] smtpAddr = "smtp.gmail.com" - smtpPort = "465" + smtpPort = "587" user = "username" password = "password" from = "from@address.com" @@ -476,6 +480,7 @@ You can customize your configuration using this template. # "cpe:/a:rubyonrails:ruby_on_rails:4.2.1", #] #containers = ["${running}"] + #ignoreCves = ["CVE-2016-6313"] #optional = [ # ["key", "value"], #] @@ -495,6 +500,7 @@ You can customize your configuration using this template. # "cpe:/a:rubyonrails:ruby_on_rails:4.2.1", #] #containers = ["${running}"] + #ignoreCves = ["CVE-2016-6314"] #optional = [ # ["key", "value"], #] @@ -508,6 +514,7 @@ You can customize your configuration using this template. - keyPath: SSH private key path - cpeNames: see [Usage: Scan vulnerability of non-OS package](https://github.com/future-architect/vuls#usage-scan-vulnerability-of-non-os-package) - containers: see [Usage: Scan Docker containers](https://github.com/future-architect/vuls#usage-scan-docker-containers) + - ignoreCves: CVE IDs that will not be reported. But output to JSON file. - optional: Add additional information to JSON report. Vuls supports two types of SSH. One is native go implementation. The other is external SSH command. For details, see [-ssh-external option](https://github.com/future-architect/vuls#-ssh-external-option) @@ -576,17 +583,22 @@ Prepare subcommand installs required packages on each server. ``` $ vuls prepare -help -prepare - [-config=/path/to/config.toml] [-debug] +prepare: + prepare + [-config=/path/to/config.toml] [-ask-key-password] - [SERVER]... + [-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 + -ssh-external + Use external ssh command. Default: Use the Go native implementation ``` ---- @@ -601,7 +613,8 @@ scan: [-lang=en|ja] [-config=/path/to/config.toml] [-results-dir=/path/to/results] - [-cve-dictionary-dbpath=/path/to/cve.sqlite3] + [-cve-dictionary-dbtype=sqlite3|mysql] + [-cve-dictionary-dbpath=/path/to/cve.sqlite3 or mysql connection string] [-cve-dictionary-url=http://127.0.0.1:1323] [-cache-dbpath=/path/to/cache.db] [-cvss-over=7] @@ -648,7 +661,9 @@ scan: -containers-only Scan concontainers Only. Default: Scan both of hosts and containers -cve-dictionary-dbpath string - /path/to/sqlite3 (For get cve detail from cve.sqlite3) + /path/to/sqlite3 (For get cve detail from cve.sqlite3) + -cve-dictionary-dbtype string + DB type for fetching CVE dictionary (sqlite3 or mysql) (default "sqlite3") -cve-dictionary-url string http://CVE.Dictionary (default "http://127.0.0.1:1323") -cvss-over float @@ -683,11 +698,11 @@ scan: Vuls supports different types of SSH. -By Defaut, using a native Go implementation from crypto/ssh. +By Default, using a native Go implementation from crypto/ssh. This is useful in situations where you may not have access to traditional UNIX tools. To use external ssh command, specify this option. -This is useful If you want to use ProxyCommand or chiper algorithm of SSH that is not supported by native go implementation. +This is useful If you want to use ProxyCommand or cipher algorithm of SSH that is not supported by native go implementation. Don't forget to add below line to /etc/sudoers on the target servers. (username: vuls) ``` Defaults:vuls !requiretty @@ -704,7 +719,7 @@ Defaults:vuls !requiretty ## -report-json , -report-text option At the end of the scan, scan results will be available in the `$PWD/result/current/` directory. -`all.(json|txt)` includes the scan results of all servres and `servername.(json|txt)` includes the scan result of the server. +`all.(json|txt)` includes the scan results of all servers and `servername.(json|txt)` includes the scan result of the server. ## Example: Scan all servers defined in config file ``` @@ -716,7 +731,7 @@ $ vuls scan \ -cve-dictionary-dbpath=$PWD/cve.sqlite3 ``` With this sample command, it will .. -- Ask SSH key passsword before scanning +- Ask SSH key password before scanning - Scan all servers defined in config file - Send scan results to slack and email - Only Report CVEs that CVSS score is over 7 @@ -780,6 +795,43 @@ $ vuls scan \ -azure-container=vuls ``` +## Example: IgnoreCves + +Define ignoreCves in config if you don't want to report(slack, mail, text...) specific CVE IDs. But these ignoreCves will be output to JSON file like below. + +- config.toml +```toml +[default] +ignoreCves = ["CVE-2016-6313"] + +[servers.bsd] +host = "192.168.11.11" +user = "kanbe" +ignoreCves = ["CVE-2016-6314"] +``` + +- bsd.json +```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 Optional key-value can be outputted to JSON. @@ -820,9 +872,17 @@ optional = [ ] ``` +## 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 +# Usage: Scan vulnerabilites of non-OS packages It is possible to detect vulnerabilities in non-OS packages, such as something you compiled by yourself, language libraries and frameworks, that have been registered in the [CPE](https://nvd.nist.gov/cpe.cfm). @@ -831,10 +891,10 @@ It is possible to detect vulnerabilities in non-OS packages, such as something y **Check CPE Naming Format: 2.2** - [go-cpe-dictionary](https://github.com/kotakanbe/go-cpe-dictionary) is a good choice for geeks. - You can search a CPE name by the application name incremenally. + You can search a CPE name by the application name incrementally. - Configuration -To detect the vulnerbility of Ruby on Rails v4.2.1, cpeNames needs to be set in the servers section. +To detect the vulnerability of Ruby on Rails v4.2.1, cpeNames needs to be set in the servers section. ``` [servers] @@ -846,10 +906,34 @@ To detect the vulnerbility of Ruby on Rails v4.2.1, cpeNames needs to be set in "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](https://www.owasp.org/index.php/OWASP_Dependency_Check) is a utility that identifies project dependencies and checks if there are any known, publicly disclosed, vulnerabilities. + +Benefit of integrating Vuls And OWASP Dependency Check is below. +- Automatic Update of Vuls config when the libraries are updated. +- Reporting by Email or Slack by using Vuls. +- Reporting in Japanese + - OWASP Dependency Check supports only English + +How to integrate Vuls with OWASP Dependency Check +- Execute OWASP Dependency Check with --format=XML option. +- Define the xml file path of dependency check in 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" + ``` + # Usage: Scan Docker containers -It is common that keep Docker containers runnning without SSHd daemon. +It is common that keep Docker containers running without SSHd daemon. see [Docker Blog:Why you don't need to run SSHd in your Docker containers](https://blog.docker.com/2014/06/why-you-dont-need-to-run-sshd-in-docker/) Vuls scans Docker containers via `docker exec` instead of SSH. @@ -901,14 +985,14 @@ tui: ``` -Key binding is bellow. +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/donw | -| Ctrl+u, Ctrl+d | page up/donw | +| 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 @@ -954,81 +1038,30 @@ $ vuls scan -cve-dictionary-url=http://192.168.0.1:1323 # Usage: Update NVD Data -``` -$ go-cve-dictionary fetchnvd -h -fetchnvd: - fetchnvd - [-last2y] - [-dbpath=/path/to/cve.sqlite3] - [-debug] - [-debug-sql] - - -dbpath string - /path/to/sqlite3 (default "$PWD/cve.sqlite3") - -debug - debug mode - -debug-sql - SQL debug mode - -last2y - Refresh NVD data in the last two years. -``` - -- Fetch data of the entire period - -``` -$ go-cve-dictionary fetchnvd -entire -``` - -- Fetch data in the last 2 years - -``` -$ go-cve-dictionary fetchnvd -last2y -``` - ----- - -# Deploy With Glide +see [go-cve-dictionary#usage-fetch-nvd-data](https://github.com/kotakanbe/go-cve-dictionary#usage-fetch-nvd-data) -If an error occurred while go get, try deploying with glide. -- Install [Glide](https://github.com/Masterminds/glide) -- Deploy go-cve-dictionary -``` -$ go get -d github.com/kotakanbe/go-cve-dictionary -$ cd $GOPATH/src/github.com/kotakanbe/go-cve-dictionary -$ glide install -$ go install -``` -- Deploy vuls -``` -$ go get -d github.com/future-architect/vuls -$ cd $GOPATH/src/github.com/future-architect/vuls -$ glide install -$ go install -``` -- The binaries are created under $GOPARH/bin ---- # Update Vuls With Glide - Update go-cve-dictionary -If the DB schema was changed, please specify new SQLite3 DB file. +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 -$ glide install -$ go install +$ mv vendor /tmp/foo +$ make install ``` - Update vuls ``` $ cd $GOPATH/src/github.com/future-architect/vuls $ git pull -$ glide install -$ go install +$ mv vendor /tmp/bar +$ make install ``` - -Binary Files are created under $GOPARH/bin +Binary file was built under $GOPARH/bin --- @@ -1044,7 +1077,7 @@ If your system is behind HTTP proxy, you have to specify --http-proxy option. - How to Daemonize go-cve-dictionary Use Systemd, Upstart or supervisord, daemontools... -- How to Enable Automatic-Update of Vunerability Data. +- How to Enable Automatic-Update of Vulnerability Data. Use job scheduler like Cron (with -last2y option). - How to Enable Automatic-Scan. @@ -1119,7 +1152,6 @@ Please see [CHANGELOG](https://github.com/future-architect/vuls/blob/master/CHAN ---- -# Licence +# License Please see [LICENSE](https://github.com/future-architect/vuls/blob/master/LICENSE). - diff --git a/commands/configtest.go b/commands/configtest.go index c2413cdb8a..e80f6f4f8a 100644 --- a/commands/configtest.go +++ b/commands/configtest.go @@ -18,6 +18,7 @@ along with this program. If not, see . package commands import ( + "context" "flag" "io/ioutil" "os" @@ -26,7 +27,6 @@ import ( "github.com/Sirupsen/logrus" "github.com/google/subcommands" - "golang.org/x/net/context" c "github.com/future-architect/vuls/config" "github.com/future-architect/vuls/scan" diff --git a/commands/discover.go b/commands/discover.go index 9e66c55ebc..4aa32e2f57 100644 --- a/commands/discover.go +++ b/commands/discover.go @@ -18,6 +18,7 @@ along with this program. If not, see . package commands import ( + "context" "flag" "fmt" "os" @@ -25,7 +26,6 @@ import ( "text/template" "github.com/google/subcommands" - "golang.org/x/net/context" "github.com/Sirupsen/logrus" ps "github.com/kotakanbe/go-pingscanner" @@ -100,7 +100,7 @@ notifyUsers = ["@username"] [mail] smtpAddr = "smtp.gmail.com" -smtpPort = "465" +smtpPort = "587" user = "username" password = "password" from = "from@address.com" @@ -115,7 +115,9 @@ subjectPrefix = "[vuls]" #cpeNames = [ # "cpe:/a:rubyonrails:ruby_on_rails:4.2.1", #] +#dependencyCheckXMLPath = "/tmp/dependency-check-report.xml" #containers = ["${running}"] +#ignoreCves = ["CVE-2014-6271"] #optional = [ # ["key", "value"], #] @@ -131,7 +133,9 @@ host = "{{$ip}}" #cpeNames = [ # "cpe:/a:rubyonrails:ruby_on_rails:4.2.1", #] +#dependencyCheckXMLPath = "/tmp/dependency-check-report.xml" #containers = ["${running}"] +#ignoreCves = ["CVE-2014-0160"] #optional = [ # ["key", "value"], #] diff --git a/commands/history.go b/commands/history.go index 4d5644a81f..9593286650 100644 --- a/commands/history.go +++ b/commands/history.go @@ -18,6 +18,7 @@ along with this program. If not, see . package commands import ( + "context" "flag" "fmt" "io/ioutil" @@ -28,7 +29,6 @@ import ( c "github.com/future-architect/vuls/config" "github.com/future-architect/vuls/report" "github.com/google/subcommands" - "golang.org/x/net/context" ) // HistoryCmd is Subcommand of list scanned results @@ -81,10 +81,6 @@ func (p *HistoryCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{ } var hosts []string for _, f := range files { - // TODO this "if block" will be deleted in a future release - if f.Name() == "all.json" { - continue - } if filepath.Ext(f.Name()) != ".json" { continue } diff --git a/commands/prepare.go b/commands/prepare.go index 5e24719f15..c44bc87653 100644 --- a/commands/prepare.go +++ b/commands/prepare.go @@ -18,6 +18,7 @@ along with this program. If not, see . package commands import ( + "context" "flag" "os" "path/filepath" @@ -27,7 +28,6 @@ import ( "github.com/future-architect/vuls/scan" "github.com/future-architect/vuls/util" "github.com/google/subcommands" - "golang.org/x/net/context" ) // PrepareCmd is Subcommand of host discovery mode @@ -37,6 +37,8 @@ type PrepareCmd struct { askSudoPassword bool askKeyPassword bool + + sshExternal bool } // Name return subcommand name @@ -60,8 +62,9 @@ func (*PrepareCmd) Usage() string { [-config=/path/to/config.toml] [-ask-key-password] [-debug] + [-ssh-external] - [SERVER]... + [SERVER]... ` } @@ -86,8 +89,15 @@ func (p *PrepareCmd) SetFlags(f *flag.FlagSet) { &p.askSudoPassword, "ask-sudo-password", false, - "[Deprecated] THIS OPTION WAS REMOVED FOR SECURITY REASON. Define NOPASSWD in /etc/sudoers on tareget servers and use SSH key-based authentication", + "[Deprecated] THIS OPTION WAS REMOVED FOR SECURITY REASONS. Define NOPASSWD in /etc/sudoers on target servers and use SSH key-based authentication", ) + + f.BoolVar( + &p.sshExternal, + "ssh-external", + false, + "Use external ssh command. Default: Use the Go native implementation") + } // Execute execute @@ -102,7 +112,7 @@ func (p *PrepareCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{ } } if p.askSudoPassword { - logrus.Errorf("[Deprecated] -ask-sudo-password WAS REMOVED FOR SECURITY REASONS. Define NOPASSWD in /etc/sudoers on tareget servers and use SSH key-based authentication") + logrus.Errorf("[Deprecated] -ask-sudo-password WAS REMOVED FOR SECURITY REASONS. Define NOPASSWD in /etc/sudoers on target servers and use SSH key-based authentication") return subcommands.ExitFailure } @@ -133,6 +143,7 @@ func (p *PrepareCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{ } c.Conf.Debug = p.debug + c.Conf.SSHExternal = p.sshExternal // Set up custom logger logger := util.NewCustomLogger(c.ServerInfo{}) @@ -149,10 +160,9 @@ func (p *PrepareCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{ return subcommands.ExitFailure } - logger.Info("Installing...") if errs := scan.Prepare(); 0 < len(errs) { for _, e := range errs { - logger.Errorf("Failed: %s", e) + logger.Errorf("Failed to prepare: %s", e) } return subcommands.ExitFailure } diff --git a/commands/scan.go b/commands/scan.go index 2f7076f32f..896f70fb13 100644 --- a/commands/scan.go +++ b/commands/scan.go @@ -18,6 +18,7 @@ along with this program. If not, see . package commands import ( + "context" "encoding/json" "flag" "fmt" @@ -34,7 +35,7 @@ import ( "github.com/future-architect/vuls/scan" "github.com/future-architect/vuls/util" "github.com/google/subcommands" - "golang.org/x/net/context" + "github.com/k0kubun/pp" ) // ScanCmd is Subcommand of host discovery mode @@ -46,6 +47,7 @@ type ScanCmd struct { configPath string resultsDir string + cvedbtype string cvedbpath string cveDictionaryURL string cacheDBPath string @@ -91,7 +93,8 @@ func (*ScanCmd) Usage() string { [-lang=en|ja] [-config=/path/to/config.toml] [-results-dir=/path/to/results] - [-cve-dictionary-dbpath=/path/to/cve.sqlite3] + [-cve-dictionary-dbtype=sqlite3|mysql] + [-cve-dictionary-dbpath=/path/to/cve.sqlite3 or mysql connection string] [-cve-dictionary-url=http://127.0.0.1:1323] [-cache-dbpath=/path/to/cache.db] [-cvss-over=7] @@ -136,6 +139,12 @@ func (p *ScanCmd) SetFlags(f *flag.FlagSet) { defaultResultsDir := filepath.Join(wd, "results") f.StringVar(&p.resultsDir, "results-dir", defaultResultsDir, "/path/to/results") + f.StringVar( + &p.cvedbtype, + "cve-dictionary-dbtype", + "sqlite3", + "DB type for fetching CVE dictionary (sqlite3 or mysql)") + f.StringVar( &p.cvedbpath, "cve-dictionary-dbpath", @@ -212,7 +221,7 @@ func (p *ScanCmd) SetFlags(f *flag.FlagSet) { f.BoolVar(&p.reportAzureBlob, "report-azure-blob", false, - "Write report to S3 (container/yyyyMMdd_HHmm/servername.json)", + "Write report to Azure Storage blob (container/yyyyMMdd_HHmm/servername.json)", ) f.StringVar(&p.azureAccount, "azure-account", "", "Azure account name to use. AZURE_STORAGE_ACCOUNT environment variable is used if not specified") f.StringVar(&p.azureKey, "azure-key", "", "Azure account key to use. AZURE_STORAGE_ACCESS_KEY environment variable is used if not specified") @@ -229,7 +238,7 @@ func (p *ScanCmd) SetFlags(f *flag.FlagSet) { &p.askSudoPassword, "ask-sudo-password", false, - "[Deprecated] THIS OPTION WAS REMOVED FOR SECURITY REASONS. Define NOPASSWD in /etc/sudoers on tareget servers and use SSH key-based authentication", + "[Deprecated] THIS OPTION WAS REMOVED FOR SECURITY REASONS. Define NOPASSWD in /etc/sudoers on target servers and use SSH key-based authentication", ) } @@ -246,11 +255,12 @@ func (p *ScanCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) } } if p.askSudoPassword { - logrus.Errorf("[Deprecated] -ask-sudo-password WAS REMOVED FOR SECURITY REASONS. Define NOPASSWD in /etc/sudoers on tareget servers and use SSH key-based authentication") + logrus.Errorf("[Deprecated] -ask-sudo-password WAS REMOVED FOR SECURITY REASONS. Define NOPASSWD in /etc/sudoers on target servers and use SSH key-based authentication") return subcommands.ExitFailure } // Load up the config file here + c.Conf.Debug = p.debug err = c.Load(p.configPath, keyPass) if err != nil { logrus.Errorf("Error loading %s, %s", p.configPath, err) @@ -260,7 +270,9 @@ func (p *ScanCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) logrus.Info("Start scanning") logrus.Infof("config: %s", p.configPath) if p.cvedbpath != "" { - logrus.Infof("cve-dictionary: %s", p.cvedbpath) + if p.cvedbtype == "sqlite3" { + logrus.Infof("cve-dictionary: %s", p.cvedbpath) + } } else { logrus.Infof("cve-dictionary: %s", p.cveDictionaryURL) } @@ -301,9 +313,9 @@ func (p *ScanCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) if 0 < len(servernames) { c.Conf.Servers = target } + logrus.Debugf("%s", pp.Sprintf("%v", target)) c.Conf.Lang = p.lang - c.Conf.Debug = p.debug c.Conf.DebugSQL = p.debugSQL // logger @@ -363,6 +375,7 @@ func (p *ScanCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) } c.Conf.ResultsDir = p.resultsDir + c.Conf.CveDBType = p.cvedbtype c.Conf.CveDBPath = p.cvedbpath c.Conf.CveDictionaryURL = p.cveDictionaryURL c.Conf.CacheDBPath = p.cacheDBPath diff --git a/commands/tui.go b/commands/tui.go index 4c7c150240..1b9cd53fc7 100644 --- a/commands/tui.go +++ b/commands/tui.go @@ -18,6 +18,7 @@ along with this program. If not, see . package commands import ( + "context" "flag" "io/ioutil" "os" @@ -28,7 +29,6 @@ import ( c "github.com/future-architect/vuls/config" "github.com/future-architect/vuls/report" "github.com/google/subcommands" - "golang.org/x/net/context" ) // TuiCmd is Subcommand of host discovery mode diff --git a/config/config.go b/config/config.go index 919ad21574..3002adda59 100644 --- a/config/config.go +++ b/config/config.go @@ -51,6 +51,7 @@ type Config struct { HTTPProxy string `valid:"url"` ResultsDir string + CveDBType string CveDBPath string CacheDBPath string @@ -77,10 +78,23 @@ func (c Config) Validate() bool { } } - if len(c.CveDBPath) != 0 { - if ok, _ := valid.IsFilePath(c.CveDBPath); !ok { - errs = append(errs, fmt.Errorf( - "SQLite3 DB(Cve Dictionary) path must be a *Absolute* file path. -cve-dictionary-dbpath: %s", c.CveDBPath)) + // If no valid DB type is set, default to sqlite3 + if c.CveDBType == "" { + c.CveDBType = "sqlite3" + } + + if c.CveDBType != "sqlite3" && c.CveDBType != "mysql" { + errs = append(errs, fmt.Errorf( + "CVE DB type must be either 'sqlite3' or 'mysql'. -cve-dictionary-dbtype: %s", c.CveDBType)) + } + + + if c.CveDBType == "sqlite3" { + if len(c.CveDBPath) != 0 { + if ok, _ := valid.IsFilePath(c.CveDBPath); !ok { + errs = append(errs, fmt.Errorf( + "SQLite3 DB(Cve Dictionary) path must be a *Absolute* file path. -cve-dictionary-dbpath: %s", c.CveDBPath)) + } } } @@ -190,7 +204,6 @@ type SlackConf struct { // Validate validates configuration func (c *SlackConf) Validate() (errs []error) { - if !c.UseThisTime { return } @@ -230,11 +243,14 @@ type ServerInfo struct { KeyPath string KeyPassword string - CpeNames []string + CpeNames []string + DependencyCheckXMLPath string // Container Names or IDs Containers []string + IgnoreCves []string + // Optional key-value set that will be outputted to JSON Optional [][]interface{} diff --git a/config/tomlloader.go b/config/tomlloader.go index c0fbb0fb19..9bad2390be 100644 --- a/config/tomlloader.go +++ b/config/tomlloader.go @@ -23,7 +23,7 @@ import ( "github.com/BurntSushi/toml" log "github.com/Sirupsen/logrus" - "github.com/k0kubun/pp" + "github.com/future-architect/vuls/contrib/owasp-dependency-check/parser" ) // TOMLLoader loads config @@ -31,7 +31,11 @@ type TOMLLoader struct { } // Load load the configuraiton TOML file specified by path arg. -func (c TOMLLoader) Load(pathToToml, keyPass string) (err error) { +func (c TOMLLoader) Load(pathToToml, keyPass string) error { + if Conf.Debug { + log.SetLevel(log.DebugLevel) + } + var conf Config if _, err := toml.DecodeFile(pathToToml, &conf); err != nil { log.Error("Load config failed", err) @@ -52,7 +56,6 @@ func (c TOMLLoader) Load(pathToToml, keyPass string) (err error) { } i := 0 for name, v := range conf.Servers { - if 0 < len(v.KeyPassword) { log.Warn("[Deprecated] KEYPASSWORD IN CONFIG FILE ARE UNSECURE. REMOVE THEM IMMEDIATELY FOR A SECURITY REASONS. THEY WILL BE REMOVED IN A FUTURE RELEASE.") } @@ -104,11 +107,42 @@ func (c TOMLLoader) Load(pathToToml, keyPass string) (err error) { s.CpeNames = d.CpeNames } + s.DependencyCheckXMLPath = v.DependencyCheckXMLPath + if len(s.DependencyCheckXMLPath) == 0 { + s.DependencyCheckXMLPath = d.DependencyCheckXMLPath + } + + // Load CPEs from OWASP Dependency Check XML + if len(s.DependencyCheckXMLPath) != 0 { + cpes, err := parser.Parse(s.DependencyCheckXMLPath) + if err != nil { + return fmt.Errorf( + "Failed to read OWASP Dependency Check XML: %s", err) + } + log.Infof("Loaded from OWASP Dependency Check XML: %s", + s.ServerName) + s.CpeNames = append(s.CpeNames, cpes...) + } + s.Containers = v.Containers if len(s.Containers) == 0 { s.Containers = d.Containers } + s.IgnoreCves = v.IgnoreCves + for _, cve := range d.IgnoreCves { + found := false + for _, c := range s.IgnoreCves { + if cve == c { + found = true + break + } + } + if !found { + s.IgnoreCves = append(s.IgnoreCves, cve) + } + } + s.Optional = v.Optional for _, dkv := range d.Optional { found := false @@ -128,8 +162,6 @@ func (c TOMLLoader) Load(pathToToml, keyPass string) (err error) { servers[name] = s } - log.Debug("Config loaded") - log.Debugf("%s", pp.Sprintf("%v", servers)) Conf.Servers = servers - return + return nil } diff --git a/contrib/owasp-dependency-check/parser/parser.go b/contrib/owasp-dependency-check/parser/parser.go new file mode 100644 index 0000000000..c0e8e81884 --- /dev/null +++ b/contrib/owasp-dependency-check/parser/parser.go @@ -0,0 +1,64 @@ +package parser + +import ( + "encoding/xml" + "fmt" + "io/ioutil" + "os" + "sort" + "strings" +) + +type analysis struct { + Dependencies []dependency `xml:"dependencies>dependency"` +} + +type dependency struct { + Identifiers []identifier `xml:"identifiers>identifier"` +} + +type identifier struct { + Name string `xml:"name"` + Type string `xml:"type,attr"` +} + +func appendIfMissing(slice []string, str string) []string { + for _, s := range slice { + if s == str { + return slice + } + } + return append(slice, str) +} + +// Parse parses XML and collect list of cpe +func Parse(path string) ([]string, error) { + file, err := os.Open(path) + if err != nil { + return []string{}, fmt.Errorf("Failed to open: %s", err) + } + defer file.Close() + + b, err := ioutil.ReadAll(file) + if err != nil { + return []string{}, fmt.Errorf("Failed to read: %s", err) + } + + var anal analysis + if err := xml.Unmarshal(b, &anal); err != nil { + fmt.Errorf("Failed to unmarshal: %s", err) + } + + cpes := []string{} + for _, d := range anal.Dependencies { + for _, ident := range d.Identifiers { + if ident.Type == "cpe" { + name := strings.TrimPrefix(ident.Name, "(") + name = strings.TrimSuffix(name, ")") + cpes = appendIfMissing(cpes, name) + } + } + } + sort.Strings(cpes) + return cpes, nil +} diff --git a/cveapi/cve_client.go b/cveapi/cve_client.go index eb33838183..44f5f282b6 100644 --- a/cveapi/cve_client.go +++ b/cveapi/cve_client.go @@ -49,7 +49,7 @@ func (api *cvedictClient) initialize() { func (api cvedictClient) CheckHealth() (ok bool, err error) { if config.Conf.CveDBPath != "" { - log.Debugf("get cve-dictionary from sqlite3") + log.Debugf("get cve-dictionary from %s", config.Conf.CveDBType) return true, nil } @@ -135,8 +135,10 @@ func (api cvedictClient) FetchCveDetails(cveIDs []string) (cveDetails cve.CveDet } func (api cvedictClient) FetchCveDetailsFromCveDB(cveIDs []string) (cveDetails cve.CveDetails, err error) { - log.Debugf("open cve-dictionary db") + log.Debugf("open cve-dictionary db (%s)", config.Conf.CveDBType) + cveconfig.Conf.DBType = config.Conf.CveDBType cveconfig.Conf.DBPath = config.Conf.CveDBPath + cveconfig.Conf.DebugSQL = config.Conf.DebugSQL if err := cvedb.OpenDB(); err != nil { return []cve.CveDetail{}, fmt.Errorf("Failed to open DB. err: %s", err) @@ -239,8 +241,11 @@ func (api cvedictClient) httpPost(key, url string, query map[string]string) ([]c } func (api cvedictClient) FetchCveDetailsByCpeNameFromDB(cpeName string) ([]cve.CveDetail, error) { - log.Debugf("open cve-dictionary db") + log.Debugf("open cve-dictionary db (%s)", config.Conf.CveDBType) + cveconfig.Conf.DBType = config.Conf.CveDBType cveconfig.Conf.DBPath = config.Conf.CveDBPath + cveconfig.Conf.DebugSQL = config.Conf.DebugSQL + if err := cvedb.OpenDB(); err != nil { return []cve.CveDetail{}, fmt.Errorf("Failed to open DB. err: %s", err) diff --git a/glide.lock b/glide.lock index efb4c1e8d6..bdc53d2bdc 100644 --- a/glide.lock +++ b/glide.lock @@ -1,10 +1,10 @@ -hash: 28d14f88e90c0765c1b660ddde796e51e197239d353bb79bfc5d8f8cf9b5f9ee -updated: 2016-09-22T12:01:23.554218373-07:00 +hash: ca64aef6e9e94c7be91f79b88edb847363c8a5bd48da4ad27784e9342c8db6e2 +updated: 2016-11-02T12:36:18.306508648-07:00 imports: - name: github.com/asaskevich/govalidator - version: 593d64559f7600f29581a3ee42177f5dbded27a9 + version: 7b3beb6df3c42abd3509abfc3bcacc0fbfb7c877 - name: github.com/aws/aws-sdk-go - version: 54888dfe736c54ceb65ccd5443d17928d90034c4 + version: 967a4b67114c61521c4b514d7c9a2feb869918e9 subpackages: - aws - aws/credentials @@ -32,44 +32,48 @@ imports: - private/protocol/xml/xmlutil - private/protocol/query/queryutil - name: github.com/Azure/azure-sdk-for-go - version: 63d3f3e3b12ffb726ba3f72fef1aa8c1c7cd1012 + version: bd73d950fa4440dae889bd9917bff7cef539f86e subpackages: - storage - name: github.com/boltdb/bolt - version: fff57c100f4dea1905678da7e90d92429dff2904 + version: 4b1ebc1869ad66568b313d0dc410e2be72670dda - name: github.com/BurntSushi/toml version: 99064174e013895bbd9b025c31100bd1d9b590ca - name: github.com/cenkalti/backoff - version: 8edc80b07f38c27352fb186d971c628a6c32552b + version: b02f2bbce11d7ea6b97f282ef1771b0fe2f65ef3 - name: github.com/cheggaaa/pb - version: ad4efe000aa550bb54918c06ebbadc0ff17687b9 + version: dd61faab99a777c652bb680e37715fe0cb549856 - name: github.com/go-ini/ini version: 6e4869b434bd001f6983749881c7ead3545887d8 +- name: github.com/go-sql-driver/mysql + version: ce924a41eea897745442daaa1739089b0f3f561d - name: github.com/google/subcommands - version: 1c7173745a6001f67d8d96ab4e178284c77f7759 + version: a71b91e238406bd68766ee52db63bebedce0e9f6 - name: github.com/gosuri/uitable version: 36ee7e946282a3fb1cfecd476ddc9b35d8847e42 subpackages: - util/strutil - util/wordwrap - name: github.com/howeyc/gopass - version: 26c6e1184fd5255fa5f5289d0b789a4819c203a4 + version: f5387c492211eb133053880d23dfae62aa14123d - name: github.com/jinzhu/gorm - version: 041cd3dd31a68a3e9ad20fcddb46085df5aebc76 + version: 4a540f3ac83a6765b8876be67994ecde022c6198 + subpackages: + - dialects/mysql - name: github.com/jinzhu/inflection version: 74387dc39a75e970e7a3ae6a3386b5bd2e5c5cff - name: github.com/jmespath/go-jmespath version: bd40a432e4c76585ef6b72d3fd96fb9b6dc7b68d - name: github.com/jroimartin/gocui - version: 30f7d65597dc2c421ce452b164c36b7014ef94be + version: 0975ddb2a85e94dfb9fcd0b8672f4a33b960fb1f - name: github.com/k0kubun/pp version: f5dce6ed0ccf6c350f1679964ff6b61f3d6d2033 - name: github.com/kotakanbe/go-cve-dictionary - version: f9f68fee57dca8e60fb5d9d6b34d3215d854fc06 + version: 70989b6709c3102924ad8c8483e9bdc99bcb598b subpackages: - config - - models - db + - models - log - jvn - nvd @@ -79,27 +83,27 @@ imports: - name: github.com/kotakanbe/logrus-prefixed-formatter version: f4f7d41649cf1e75e736884da8d05324aa76ea25 - name: github.com/mattn/go-colorable - version: ed8eb9e318d7a84ce5915b495b7d35e0cfe7b5a8 + version: 6e26b354bd2b0fc420cb632b0d878abccdc6544c - name: github.com/mattn/go-isatty version: 66b8e73f3f5cda9f96b69efd03dd3d7fc4a5cdb8 - name: github.com/mattn/go-runewidth - version: d6bea18f789704b5f83375793155289da36a3c7f + version: 737072b4e32b7a5018b4a7125da8d12de90e8045 - name: github.com/mattn/go-sqlite3 - version: 3fb7a0e792edd47bf0cf1e919dfc14e2be412e15 + version: 86681de00adef4f8040947b7d35f97000fc5a230 - name: github.com/mgutz/ansi version: c286dcecd19ff979eeb73ea444e479b903f2cfcb - name: github.com/moul/http2curl - version: b1479103caacaa39319f75e7f57fc545287fca0d + version: 4e24498b31dba4683efb9d35c1c8a91e2eda28c8 - name: github.com/nsf/termbox-go version: b6acae516ace002cb8105a89024544a1480655a5 - name: github.com/parnurzeal/gorequest - version: 29ced6f360a5ac3823a3675b4e29fbab336cc186 + version: b8943263f1ae87258d26a5c2181d1bc71deeddc0 - name: github.com/rifflock/lfshook version: 3f9d976bd7402de39b46357069fb6325a974572e - name: github.com/Sirupsen/logrus - version: 3ec0642a7fb6488f65b06f9040adc67e3990296a + version: 380f64d344b252a007a59baa61f31820f59cba89 - name: golang.org/x/crypto - version: 8e06e8ddd9629eb88639aba897641bff8031f1d3 + version: 9477e0b78b9ac3d0b03822fd95422e2fe07627cd subpackages: - ssh - ssh/agent @@ -108,16 +112,12 @@ imports: - ed25519 - ed25519/internal/edwards25519 - name: golang.org/x/net - version: 6d3beaea10370160dea67f5c9327ed791afd5389 + version: 4bb47a1098b37d69980d96237e2ae4ff56bb5a95 subpackages: - context - publicsuffix - name: golang.org/x/sys - version: 8f0908ab3b2457e2e15403d3697c9ef5cb4b57a9 + version: c200b10b5d5e122be351b67af224adc6128af5bf subpackages: - unix -- name: gopkg.in/alexcesaro/quotedprintable.v3 - version: 2caba252f4dc53eaf6b553000885530023f54623 -- name: gopkg.in/gomail.v2 - version: 81ebce5c23dfd25c6c67194b37d3dd3f338c98b1 testImports: [] diff --git a/glide.yaml b/glide.yaml index 015240a5dd..4608cf17aa 100644 --- a/glide.yaml +++ b/glide.yaml @@ -12,6 +12,7 @@ import: - aws/credentials - aws/session - service/s3 +- package: github.com/boltdb/bolt - package: github.com/cenkalti/backoff - package: github.com/google/subcommands - package: github.com/gosuri/uitable @@ -22,6 +23,7 @@ import: - package: github.com/kotakanbe/go-cve-dictionary subpackages: - config + - db - models - package: github.com/kotakanbe/go-pingscanner - package: github.com/kotakanbe/logrus-prefixed-formatter @@ -35,4 +37,3 @@ import: - package: golang.org/x/net subpackages: - context -- package: gopkg.in/gomail.v2 diff --git a/main.go b/main.go index 35acb99b0e..e96c6bce49 100644 --- a/main.go +++ b/main.go @@ -22,15 +22,20 @@ import ( "fmt" "os" - "golang.org/x/net/context" + "context" "github.com/future-architect/vuls/commands" - "github.com/future-architect/vuls/version" "github.com/google/subcommands" _ "github.com/mattn/go-sqlite3" ) +// Version of Vuls +var version = "0.1.6" + +// Revision of Git +var revision string + func main() { subcommands.Register(subcommands.HelpCommand(), "") subcommands.Register(subcommands.FlagsCommand(), "") @@ -47,7 +52,7 @@ func main() { flag.Parse() if *v { - fmt.Printf("%s %s\n", version.Name, version.Version) + fmt.Printf("vuls %s %s\n", version, revision) os.Exit(int(subcommands.ExitSuccess)) } diff --git a/models/models.go b/models/models.go index 7c862cfe18..3a1877748d 100644 --- a/models/models.go +++ b/models/models.go @@ -89,6 +89,7 @@ type ScanResult struct { // NWLinks []NWLink KnownCves []CveInfo UnknownCves []CveInfo + IgnoredCves []CveInfo Optional [][]interface{} `gorm:"-"` } diff --git a/report/json.go b/report/json.go index 4781187453..acff8c8921 100644 --- a/report/json.go +++ b/report/json.go @@ -61,14 +61,6 @@ func (w JSONWriter) Write(scanResults []models.ScanResult) (err error) { } var jsonBytes []byte - if jsonBytes, err = json.Marshal(scanResults); err != nil { - return fmt.Errorf("Failed to Marshal to JSON: %s", err) - } - all := filepath.Join(path, "all.json") - if err := ioutil.WriteFile(all, jsonBytes, 0600); err != nil { - return fmt.Errorf("Failed to write JSON. path: %s, err: %s", all, err) - } - for _, r := range scanResults { jsonPath := "" if len(r.Container.ContainerID) == 0 { @@ -117,10 +109,6 @@ func LoadOneScanHistory(jsonDir string) (scanHistory models.ScanHistory, err err return } for _, file := range files { - // TODO this "if block" will be deleted in a future release - if file.Name() == "all.json" { - continue - } if filepath.Ext(file.Name()) != ".json" { continue } diff --git a/report/mail.go b/report/mail.go index 34cd3febde..21803874be 100644 --- a/report/mail.go +++ b/report/mail.go @@ -18,13 +18,14 @@ along with this program. If not, see . package report import ( - "crypto/tls" "fmt" - "strconv" + "net" + "net/mail" + "net/smtp" + "strings" "github.com/future-architect/vuls/config" "github.com/future-architect/vuls/models" - "gopkg.in/gomail.v2" ) // MailWriter send mail @@ -33,37 +34,53 @@ type MailWriter struct{} func (w MailWriter) Write(scanResults []models.ScanResult) (err error) { conf := config.Conf for _, s := range scanResults { - m := gomail.NewMessage() - m.SetHeader("From", conf.Mail.From) - m.SetHeader("To", conf.Mail.To...) - m.SetHeader("Cc", conf.Mail.Cc...) + to := strings.Join(conf.Mail.To[:], ", ") + cc := strings.Join(conf.Mail.Cc[:], ", ") + mailAddresses := append(conf.Mail.To, conf.Mail.Cc...) + if _, err := mail.ParseAddressList(strings.Join(mailAddresses[:], ", ")); err != nil { + return fmt.Errorf("Failed to parse email addresses: %s", err) + } subject := fmt.Sprintf("%s%s %s", conf.Mail.SubjectPrefix, s.ServerInfo(), s.CveSummary(), ) - m.SetHeader("Subject", subject) + + headers := make(map[string]string) + headers["From"] = conf.Mail.From + headers["To"] = to + headers["Cc"] = cc + headers["Subject"] = subject + + var message string + for k, v := range headers { + message += fmt.Sprintf("%s: %s\r\n", k, v) + } var body string if body, err = toPlainText(s); err != nil { return err } - m.SetBody("text/plain", body) - port, _ := strconv.Atoi(conf.Mail.SMTPPort) - d := gomail.NewPlainDialer( - conf.Mail.SMTPAddr, - port, - conf.Mail.User, - conf.Mail.Password, - ) + message += "\r\n" + body - d.TLSConfig = &tls.Config{ - InsecureSkipVerify: true, - } + smtpServer := net.JoinHostPort(conf.Mail.SMTPAddr, conf.Mail.SMTPPort) + + err := smtp.SendMail( + smtpServer, + smtp.PlainAuth( + "", + conf.Mail.User, + conf.Mail.Password, + conf.Mail.SMTPAddr, + ), + conf.Mail.From, + conf.Mail.To, + []byte(message), + ) - if err := d.DialAndSend(m); err != nil { - panic(err) + if err != nil { + return fmt.Errorf("Failed to send emails: %s", err) } } return nil diff --git a/report/s3.go b/report/s3.go index 95b7951ea8..f55484101a 100644 --- a/report/s3.go +++ b/report/s3.go @@ -78,16 +78,6 @@ func (w S3Writer) Write(scanResults []models.ScanResult) (err error) { // http://docs.aws.amazon.com/sdk-for-go/latest/v1/developerguide/common-examples.title.html svc := getS3() timestr := time.Now().Format("20060102_1504") - key := fmt.Sprintf("%s/%s", timestr, "all.json") - _, err = svc.PutObject(&s3.PutObjectInput{ - Bucket: &c.Conf.S3Bucket, - Key: &key, - Body: bytes.NewReader(jsonBytes), - }) - if err != nil { - return fmt.Errorf("Failed to upload data to %s/%s, %s", c.Conf.S3Bucket, key, err) - } - for _, r := range scanResults { key := "" if len(r.Container.ContainerID) == 0 { diff --git a/report/slack.go b/report/slack.go index c0faa437a1..655445e67f 100644 --- a/report/slack.go +++ b/report/slack.go @@ -59,7 +59,6 @@ type SlackWriter struct{} func (w SlackWriter) Write(scanResults []models.ScanResult) error { conf := config.Conf.Slack for _, s := range scanResults { - channel := conf.Channel if channel == "${servername}" { channel = fmt.Sprintf("#%s", s.ServerName) @@ -97,7 +96,6 @@ func (w SlackWriter) Write(scanResults []models.ScanResult) error { } func msgText(r models.ScanResult) string { - notifyUsers := "" if 0 < len(r.KnownCves) || 0 < len(r.UnknownCves) { notifyUsers = getNotifyUsers(config.Conf.Slack.NotifyUsers) @@ -108,7 +106,6 @@ func msgText(r models.ScanResult) string { } func toSlackAttachments(scanResult models.ScanResult) (attaches []*attachment) { - cves := scanResult.KnownCves if !config.Conf.IgnoreUnscoredCves { cves = append(cves, scanResult.UnknownCves...) diff --git a/report/tui.go b/report/tui.go index 4a41635bc8..2b2477d2fc 100644 --- a/report/tui.go +++ b/report/tui.go @@ -44,26 +44,28 @@ func RunTui(jsonDirName string) subcommands.ExitStatus { var err error scanHistory, err = selectScanHistory(jsonDirName) if err != nil { - log.Fatal(err) + log.Errorf("%s", err) return subcommands.ExitFailure } - g := gocui.NewGui() - if err := g.Init(); err != nil { - log.Panicln(err) + g, err := gocui.NewGui() + if err != nil { + log.Errorf("%s", err) + return subcommands.ExitFailure } defer g.Close() - g.SetLayout(layout) + g.SetManagerFunc(layout) if err := keybindings(g); err != nil { - log.Panicln(err) + log.Errorf("%s", err) + return subcommands.ExitFailure } g.SelBgColor = gocui.ColorGreen g.SelFgColor = gocui.ColorBlack g.Cursor = true if err := g.MainLoop(); err != nil && err != gocui.ErrQuit { - log.Panicln(err) + log.Errorf("%s", err) return subcommands.ExitFailure } @@ -174,35 +176,41 @@ func keybindings(g *gocui.Gui) (err error) { } func nextView(g *gocui.Gui, v *gocui.View) error { + var err error + if v == nil { - return g.SetCurrentView("side") + _, err = g.SetCurrentView("side") } switch v.Name() { case "side": - return g.SetCurrentView("summary") + _, err = g.SetCurrentView("summary") case "summary": - return g.SetCurrentView("detail") + _, err = g.SetCurrentView("detail") case "detail": - return g.SetCurrentView("side") + _, err = g.SetCurrentView("side") default: - return g.SetCurrentView("summary") + _, err = g.SetCurrentView("summary") } + return err } func previousView(g *gocui.Gui, v *gocui.View) error { + var err error + if v == nil { - return g.SetCurrentView("side") + _, err = g.SetCurrentView("side") } switch v.Name() { case "side": - return g.SetCurrentView("side") + _, err = g.SetCurrentView("side") case "summary": - return g.SetCurrentView("side") + _, err = g.SetCurrentView("side") case "detail": - return g.SetCurrentView("summary") + _, err = g.SetCurrentView("summary") default: - return g.SetCurrentView("side") + _, err = g.SetCurrentView("side") } + return err } func movable(v *gocui.View, nextY int) (ok bool, yLimit int) { @@ -371,7 +379,7 @@ func cursorPageUp(g *gocui.Gui, v *gocui.View) error { func previousSummary(g *gocui.Gui, v *gocui.View) error { if v != nil { // cursor to summary - if err := g.SetCurrentView("summary"); err != nil { + if _, err := g.SetCurrentView("summary"); err != nil { return err } // move next line @@ -379,7 +387,7 @@ func previousSummary(g *gocui.Gui, v *gocui.View) error { return err } // cursor to detail - if err := g.SetCurrentView("detail"); err != nil { + if _, err := g.SetCurrentView("detail"); err != nil { return err } } @@ -389,7 +397,7 @@ func previousSummary(g *gocui.Gui, v *gocui.View) error { func nextSummary(g *gocui.Gui, v *gocui.View) error { if v != nil { // cursor to summary - if err := g.SetCurrentView("summary"); err != nil { + if _, err := g.SetCurrentView("summary"); err != nil { return err } // move next line @@ -397,7 +405,7 @@ func nextSummary(g *gocui.Gui, v *gocui.View) error { return err } // cursor to detail - if err := g.SetCurrentView("detail"); err != nil { + if _, err := g.SetCurrentView("detail"); err != nil { return err } } @@ -462,7 +470,7 @@ func getLine(g *gocui.Gui, v *gocui.View) error { return err } fmt.Fprintln(v, l) - if err := g.SetCurrentView("msg"); err != nil { + if _, err := g.SetCurrentView("msg"); err != nil { return err } } @@ -484,7 +492,7 @@ func showMsg(g *gocui.Gui, v *gocui.View) error { return err } fmt.Fprintln(v, l) - if err := g.SetCurrentView("msg"); err != nil { + if _, err := g.SetCurrentView("msg"); err != nil { return err } } @@ -495,7 +503,7 @@ func delMsg(g *gocui.Gui, v *gocui.View) error { if err := g.DeleteView("msg"); err != nil { return err } - if err := g.SetCurrentView("summary"); err != nil { + if _, err := g.SetCurrentView("summary"); err != nil { return err } return nil @@ -530,7 +538,7 @@ func setSideLayout(g *gocui.Gui) error { fmt.Fprintln(v, result.ServerInfoTui()) } currentScanResult = scanHistory.ScanResults[0] - if err := g.SetCurrentView("side"); err != nil { + if _, err := g.SetCurrentView("side"); err != nil { return err } } diff --git a/scan/base.go b/scan/base.go index 7b9c3c81e5..a7361575a8 100644 --- a/scan/base.go +++ b/scan/base.go @@ -33,8 +33,9 @@ import ( type base struct { ServerInfo config.ServerInfo Distro config.Distro + Platform models.Platform - Platform models.Platform + lackDependencies []string osPackages log *logrus.Entry @@ -85,6 +86,10 @@ func (l base) getPlatform() models.Platform { return l.Platform } +func (l base) getLackDependencies() []string { + return l.lackDependencies +} + func (l base) allContainers() (containers []config.Container, err error) { switch l.ServerInfo.Container.Type { case "", "docker": @@ -227,13 +232,31 @@ func (l base) isAwsInstanceID(str string) bool { } func (l *base) convertToModel() (models.ScanResult, error) { - var scoredCves, unscoredCves models.CveInfos + var scoredCves, unscoredCves, ignoredCves models.CveInfos for _, p := range l.UnsecurePackages { + // ignoreCves + found := false + for _, icve := range l.getServerInfo().IgnoreCves { + if icve == p.CveDetail.CveID { + ignoredCves = append(ignoredCves, models.CveInfo{ + CveDetail: p.CveDetail, + Packages: p.Packs, + DistroAdvisories: p.DistroAdvisories, + }) + found = true + break + } + } + if found { + continue + } + + // unscoredCves if p.CveDetail.CvssScore(config.Conf.Lang) <= 0 { unscoredCves = append(unscoredCves, models.CveInfo{ CveDetail: p.CveDetail, Packages: p.Packs, - DistroAdvisories: p.DistroAdvisories, // only Amazon Linux + DistroAdvisories: p.DistroAdvisories, }) continue } @@ -244,10 +267,11 @@ func (l *base) convertToModel() (models.ScanResult, error) { models.CpeName{Name: cpename}) } + // scoredCves cve := models.CveInfo{ CveDetail: p.CveDetail, Packages: p.Packs, - DistroAdvisories: p.DistroAdvisories, // only Amazon Linux + DistroAdvisories: p.DistroAdvisories, CpeNames: cpenames, } scoredCves = append(scoredCves, cve) @@ -260,6 +284,7 @@ func (l *base) convertToModel() (models.ScanResult, error) { sort.Sort(scoredCves) sort.Sort(unscoredCves) + sort.Sort(ignoredCves) return models.ScanResult{ ServerName: l.ServerInfo.ServerName, @@ -270,6 +295,7 @@ func (l *base) convertToModel() (models.ScanResult, error) { Platform: l.Platform, KnownCves: scoredCves, UnknownCves: unscoredCves, + IgnoredCves: ignoredCves, Optional: l.ServerInfo.Optional, }, nil } diff --git a/scan/debian.go b/scan/debian.go index cc941c4b21..2f5e757cd5 100644 --- a/scan/debian.go +++ b/scan/debian.go @@ -124,7 +124,31 @@ func (o *debian) checkIfSudoNoPasswd() error { return nil } +func (o *debian) checkDependencies() error { + switch o.Distro.Family { + case "ubuntu": + return nil + + case "debian": + // Debian needs aptitude to get changelogs. + // Because unable to get changelogs via apt-get changelog on Debian. + name := "aptitude" + cmd := name + " -h" + if r := o.ssh(cmd, noSudo); !r.isSuccess() { + o.lackDependencies = []string{name} + } + return nil + + default: + return fmt.Errorf("Not implemented yet: %s", o.Distro) + } +} + func (o *debian) install() error { + if len(o.lackDependencies) == 0 { + return nil + } + // apt-get update o.log.Infof("apt-get update...") cmd := util.PrependProxyEnv("apt-get update") @@ -134,15 +158,14 @@ func (o *debian) install() error { return fmt.Errorf(msg) } - if o.Distro.Family == "debian" { - // install aptitude - cmd = util.PrependProxyEnv("apt-get install --force-yes -y aptitude") + for _, name := range o.lackDependencies { + cmd = util.PrependProxyEnv("apt-get install " + name) if r := o.exec(cmd, sudo); !r.isSuccess() { msg := fmt.Sprintf("Failed to SSH: %s", r) o.log.Errorf(msg) return fmt.Errorf(msg) } - o.log.Infof("Installed: aptitude") + o.log.Infof("Installed: " + name) } return nil } @@ -302,7 +325,7 @@ func (o *debian) fillCandidateVersion(before models.PackageInfoList) (filled []m for _, p := range before { names = append(names, p.Name) } - cmd := fmt.Sprintf("LANG=en_US.UTF-8 apt-cache policy %s", strings.Join(names, " ")) + cmd := fmt.Sprintf("LANGUAGE=en_US.UTF-8 apt-cache policy %s", strings.Join(names, " ")) r := o.exec(cmd, noSudo) if !r.isSuccess() { return nil, fmt.Errorf("Failed to SSH: %s.", r) @@ -324,7 +347,7 @@ func (o *debian) fillCandidateVersion(before models.PackageInfoList) (filled []m } func (o *debian) GetUpgradablePackNames() (packNames []string, err error) { - cmd := util.PrependProxyEnv("LANG=en_US.UTF-8 apt-get upgrade --dry-run") + cmd := util.PrependProxyEnv("LANGUAGE=en_US.UTF-8 apt-get upgrade --dry-run") r := o.exec(cmd, noSudo) if r.isSuccess(0, 1) { return o.parseAptGetUpgrade(r.Stdout) @@ -494,7 +517,7 @@ func (o *debian) getChangelogCache(meta cache.Meta, pack models.PackageInfo) str } changelog, err := cache.DB.GetChangelog(meta.Name, pack.Name) if err != nil { - o.log.Warnf("Failed to get chnagelog. bucket: %s, key:%s, err: %s", + o.log.Warnf("Failed to get changelog. bucket: %s, key:%s, err: %s", meta.Name, pack.Name, err) return "" } @@ -522,11 +545,13 @@ func (o *debian) scanPackageCveIDs(pack models.PackageInfo) ([]string, error) { o.log.Warnf("Failed to SSH: %s", r) // Ignore this Error. return nil, nil - } - err := cache.DB.PutChangelog(o.getServerInfo().GetServerName(), pack.Name, r.Stdout) - if err != nil { - return nil, fmt.Errorf("Failed to put changelog into cache") + + if 0 < len(strings.TrimSpace(r.Stdout)) { + err := cache.DB.PutChangelog(o.getServerInfo().GetServerName(), pack.Name, r.Stdout) + if err != nil { + return nil, fmt.Errorf("Failed to put changelog into cache") + } } // No error will be returned. Only logging. return o.getCveIDFromChangelog(r.Stdout, pack.Name, pack.Version), nil diff --git a/scan/freebsd.go b/scan/freebsd.go index 7bce026fe5..744eb81a19 100644 --- a/scan/freebsd.go +++ b/scan/freebsd.go @@ -65,6 +65,10 @@ func (o *bsd) checkIfSudoNoPasswd() error { return nil } +func (o *bsd) checkDependencies() error { + return nil +} + func (o *bsd) install() error { return nil } diff --git a/scan/freebsd_test.go b/scan/freebsd_test.go index 2351f2b299..48dd62b1a2 100644 --- a/scan/freebsd_test.go +++ b/scan/freebsd_test.go @@ -139,17 +139,17 @@ WWW: https://vuxml.FreeBSD.org/freebsd/ab3e98d9-8175-11e4-907d-d050992ecde8.html d := newBsd(config.ServerInfo{}) for _, tt := range tests { - aName, aCveIDs, aVunlnID := d.parseBlock(tt.in) + aName, aCveIDs, aVulnID := d.parseBlock(tt.in) if tt.name != aName { - t.Errorf("expected vulnID: %s, actual %s", tt.vulnID, aVunlnID) + t.Errorf("expected vulnID: %s, actual %s", tt.vulnID, aVulnID) } for i := range tt.cveIDs { if tt.cveIDs[i] != aCveIDs[i] { t.Errorf("expected cveID: %s, actual %s", tt.cveIDs[i], aCveIDs[i]) } } - if tt.vulnID != aVunlnID { - t.Errorf("expected vulnID: %s, actual %s", tt.vulnID, aVunlnID) + if tt.vulnID != aVulnID { + t.Errorf("expected vulnID: %s, actual %s", tt.vulnID, aVulnID) } } } diff --git a/scan/redhat.go b/scan/redhat.go index 22bdf6818a..53b640e72c 100644 --- a/scan/redhat.go +++ b/scan/redhat.go @@ -112,45 +112,46 @@ func (o *redhat) checkIfSudoNoPasswd() error { // CentOS 6 ... yum-plugin-changelog // CentOS 7 ... yum-plugin-changelog // RHEL, Amazon ... no additinal packages needed -func (o *redhat) install() error { +func (o *redhat) checkDependencies() error { switch o.Distro.Family { case "rhel", "amazon": - o.log.Infof("Nothing to do") + // o.log.Infof("Nothing to do") return nil - } - // CentOS - return o.installYumChangelog() -} -func (o *redhat) installYumChangelog() error { - if o.Distro.Family == "centos" { + case "centos": var majorVersion int if 0 < len(o.Distro.Release) { majorVersion, _ = strconv.Atoi(strings.Split(o.Distro.Release, ".")[0]) } else { - return fmt.Errorf( - "Not implemented yet: %s", o.Distro) + return fmt.Errorf("Not implemented yet: %s", o.Distro) } - var packName = "" + var name = "" if majorVersion < 6 { - packName = "yum-changelog" + name = "yum-changelog" } else { - packName = "yum-plugin-changelog" + name = "yum-plugin-changelog" } - cmd := "rpm -q " + packName + cmd := "rpm -q " + name if r := o.exec(cmd, noSudo); r.isSuccess() { - o.log.Infof("Ignored: %s already installed", packName) return nil } + o.lackDependencies = []string{name} + return nil - o.log.Infof("Installing %s...", packName) - cmd = util.PrependProxyEnv("yum install -y " + packName) + default: + return fmt.Errorf("Not implemented yet: %s", o.Distro) + } +} + +func (o *redhat) install() error { + for _, name := range o.lackDependencies { + cmd := util.PrependProxyEnv("yum install -y " + name) if r := o.exec(cmd, sudo); !r.isSuccess() { return fmt.Errorf("Failed to SSH: %s", r) } - o.log.Infof("Installed: %s", packName) + o.log.Infof("Installed: %s", name) } return nil } @@ -252,7 +253,7 @@ func (o *redhat) scanUnsecurePackages() ([]CvePacksInfo, error) { // For CentOS func (o *redhat) scanUnsecurePackagesUsingYumCheckUpdate() (CvePacksList, error) { - cmd := "LANG=en_US.UTF-8 yum --color=never check-update" + cmd := "LANGUAGE=en_US.UTF-8 yum --color=never check-update" r := o.exec(util.PrependProxyEnv(cmd), sudo) if !r.isSuccess(0, 100) { //returns an exit code of 100 if there are available updates. @@ -408,7 +409,7 @@ func (o *redhat) parseYumCheckUpdateLines(stdout string) (results models.Package func (o *redhat) parseYumCheckUpdateLine(line string) (models.PackageInfo, error) { fields := strings.Fields(line) - if len(fields) != 3 { + if len(fields) < 3 { return models.PackageInfo{}, fmt.Errorf("Unknown format: %s", line) } splitted := strings.Split(fields[0], ".") @@ -548,7 +549,7 @@ func (o *redhat) getAllChangelog(packInfoList models.PackageInfoList) (stdout st } // yum update --changelog doesn't have --color option. - command += fmt.Sprintf(" LANG=en_US.UTF-8 yum update --changelog %s", packageNames) + command += fmt.Sprintf(" LANGUAGE=en_US.UTF-8 yum update --changelog %s", packageNames) r := o.exec(command, sudo) if !r.isSuccess(0, 1) { @@ -590,7 +591,7 @@ func (o *redhat) scanUnsecurePackagesUsingYumPluginSecurity() (CvePacksList, err // get package name, version, rel to be upgrade. // cmd = "yum check-update --security" - cmd = "LANG=en_US.UTF-8 yum --color=never check-update" + cmd = "LANGUAGE=en_US.UTF-8 yum --color=never check-update" r = o.exec(util.PrependProxyEnv(cmd), o.sudo()) if !r.isSuccess(0, 100) { //returns an exit code of 100 if there are available updates. diff --git a/scan/redhat_test.go b/scan/redhat_test.go index 9bd87f2665..60a5df7cd4 100644 --- a/scan/redhat_test.go +++ b/scan/redhat_test.go @@ -616,6 +616,7 @@ Obsoleting Packages python-libs.i686 2.6.6-64.el6 rhui-REGION-rhel-server-releases python-ordereddict.noarch 1.1-3.el6ev installed bind-utils.x86_64 30:9.3.6-25.P1.el5_11.8 updates +pytalloc.x86_64 2.0.7-2.el6 @CentOS 6.5/6.5 ` r.Packages = []models.PackageInfo{ @@ -644,6 +645,11 @@ bind-utils.x86_64 30:9.3.6-25.P1.el5_11.8 updates Version: "1.0", Release: "1", }, + { + Name: "pytalloc", + Version: "2.0.1", + Release: "0", + }, } var tests = []struct { in string @@ -687,6 +693,13 @@ bind-utils.x86_64 30:9.3.6-25.P1.el5_11.8 updates NewVersion: "9.3.6", NewRelease: "25.P1.el5_11.8", }, + { + Name: "pytalloc", + Version: "2.0.1", + Release: "0", + NewVersion: "2.0.7", + NewRelease: "2.el6", + }, }, }, } diff --git a/scan/serverapi.go b/scan/serverapi.go index 78e838068b..bf0efef7d1 100644 --- a/scan/serverapi.go +++ b/scan/serverapi.go @@ -18,7 +18,10 @@ along with this program. If not, see . package scan import ( + "bufio" "fmt" + "os" + "strings" "time" "github.com/Sirupsen/logrus" @@ -40,7 +43,10 @@ type osTypeInterface interface { setDistro(string, string) getDistro() config.Distro - // getFamily() string + + // checkDependencies checks if dependencies are installed on the target server. + checkDependencies() error + getLackDependencies() []string checkIfSudoNoPasswd() error detectPlatform() error @@ -60,7 +66,7 @@ type osTypeInterface interface { setErrs([]error) } -// osPackages included by linux struct +// osPackages is included by base struct type osPackages struct { // installed packages Packages models.PackageInfoList @@ -424,12 +430,65 @@ func detectPlatforms() []error { // Prepare installs requred packages to scan vulnerabilities. func Prepare() []error { - return parallelSSHExec(func(o osTypeInterface) error { + errs := parallelSSHExec(func(o osTypeInterface) error { + if err := o.checkDependencies(); err != nil { + return err + } + return nil + }) + if len(errs) != 0 { + return errs + } + + var targets []osTypeInterface + for _, s := range servers { + deps := s.getLackDependencies() + if len(deps) != 0 { + targets = append(targets, s) + } + } + if len(targets) == 0 { + Log.Info("No need to install dependencies") + return nil + } + + Log.Info("Below servers are needed to install dependencies") + for _, s := range targets { + for _, d := range s.getLackDependencies() { + Log.Infof(" - %s on %s", d, s.getServerInfo().GetServerName()) + } + } + Log.Info("Is this ok to install dependencies on the servers? [y/N]") + + reader := bufio.NewReader(os.Stdin) + for { + text, err := reader.ReadString('\n') + if err != nil { + return []error{err} + } + switch strings.TrimSpace(text) { + case "", "N", "n": + return nil + case "y", "Y": + goto yes + default: + Log.Info("Please enter y or N") + } + } + +yes: + servers = targets + errs = parallelSSHExec(func(o osTypeInterface) error { if err := o.install(); err != nil { return err } return nil }) + if len(errs) != 0 { + return errs + } + Log.Info("All dependencies were installed correctly") + return nil } // Scan scan @@ -450,7 +509,7 @@ func Scan() []error { defer func() { if cache.DB != nil { - defer cache.DB.Close() + cache.DB.Close() } }() diff --git a/setup/docker/README.ja.md b/setup/docker/README.ja.md deleted file mode 100644 index 831060c8d1..0000000000 --- a/setup/docker/README.ja.md +++ /dev/null @@ -1,101 +0,0 @@ -# Vuls on Docker - -## What's Vuls-On-Docker - -- 数個のコマンドを実行するだけでVulsとvulsrepoのセットアップが出来るスクリプト -- Dockerコンテナ上にVulsと[vulsrepo](https://github.com/usiusi360/vulsrepo)をセットアップ可能 -- スキャン結果をvulsrepoでブラウザで分析可能 -- 脆弱性データベースの更新が可能 -- モジュールのアップデートが可能 - -## Setting up your machine - -1. [Install Docker](https://docs.docker.com/engine/installation/) -2. [Install Docker-Compose](https://docs.docker.com/compose/install/) -3. 実行前に以下のコマンドが実行可能なことを確認する - - ``` - $ docker version - $ docker-compose version - ``` - -4. Vulsをgit clone - ``` - mkdir work - cd work - git clone https://github.com/future-architect/vuls.git - cd vuls/setup/docker - ``` - -## Start A Vuls Container - -- 以下のコマンドを実行してコンテナをビルドする - - ``` - $ docker-compose up -d - ``` - -## Setting up Vuls - -1. スキャン対象サーバのSSH秘密鍵を保存(vuls/setup/docker/conf/)する -2. config.toml(vuls/setup/docker/conf/config.toml) を環境に合わせて作成する - - ``` - [servers] - - [servers.172-31-4-82] - host = "172.31.4.82" - user = "ec2-user" - keyPath = "conf/id_rsa" - ``` - -## Fetch Vulnerability database - -- NVDから脆弱性データベースを取得する - ``` - $ docker exec -t vuls scripts/fetch_nvd_all.sh - ``` - -- レポートを日本語化する場合は、JVNから脆弱性データを取得する - ``` - $ docker exec -t vuls scripts/fetch_jvn_all.sh - ``` - -## Scan servers with Vuls-On-Docker - -- スキャンを実行する - - ``` - $ docker exec -t vuls vuls prepare -config=conf/config.toml - $ docker exec -t vuls scripts/scan_for_vulsrepo.sh - ``` - -## See the results in a browser - -``` -http://${Vuls_Host}/vulsrepo/ -``` - -# Update modules - -- vuls, go-cve-dictionary, vulsrepoのモジュールをアップデートする - ``` - $ docker exec -t vuls scripts/update_modules.sh - ``` - -# Update Vulnerability database - -- NVDの過去2年分の脆弱性データベースを更新する - ``` - $ docker exec -t vuls scripts/fetch_nvd_last2y.sh - ``` - -- JVNの過去1ヶ月分の脆弱性データベースを更新する - ``` - $ docker exec -t vuls scripts/fetch_jvn_month.sh - ``` - -- JVNの過去1週間分の脆弱性データベースを更新する - ``` - $ docker exec -t vuls scripts/fetch_jvn_week.sh - ``` diff --git a/setup/docker/README.md b/setup/docker/README.md index 2df2d58d59..d72aae70c2 100644 --- a/setup/docker/README.md +++ b/setup/docker/README.md @@ -1,87 +1,183 @@ -# Vuls on Docker +# Vuls Docker components -## What's Vuls-On-Docker +This is the Git repo of the official Docker image for vuls. -- This is a dockernized-Vuls with vulsrepo UI in it. -- It's designed to reduce the cost of installation and the dependencies that vuls requires. -- You can run install and run Vuls on your machine with only a few commands. -- The result can be viewed with a browser +# Supported tags and respective `Dockerfile` links -## Setting up your machine - -1. [Install Docker](https://docs.docker.com/engine/installation/) -2. [Install Docker-Compose](https://docs.docker.com/compose/install/) -3. Make sure that you can run the following commands before you move on. +- go-cve-dictionary + - [`latest` (*go-cve-dictionary:latest Dockerfile*)]() +- vuls + - [`latest` (*vuls:latest Dockerfile*)]() +- vulsrepo + - [`latest` (*vulsrepo:latest Dockerfile*)]() - ``` - $ docker version - $ docker-compose version - ``` - -4. git clone vuls - ``` - mkdir work - cd work - git clone https://github.com/future-architect/vuls.git - cd vuls/setup/docker - ``` +This image version is same as the github repository version. +# Caution +This image is built per commit. +If you want to use the latest docker image, you should remove the existing image, and pull it once again. -## Start A Vuls Container +1. Confirm your vuls version -- Execute the following command to build and run a Vuls Container +- go-cve-dictionary - ``` - $ docker-compose up -d - ``` +```console +$ docker run --rm vuls/go-cve-dictionary -v -## Setting up Vuls +go-cve-dictionary v0.0.xxx xxxx +``` + +- vuls + +```console +$ docker run --rm vuls/vuls -v + +vuls v0.0.xxx xxxx +``` + +2. Remove your old docker images + +- go-cve-dictionary + +``` +$ docker rmi vuls/go-cve-dictionary +``` + +``` +$ docker rmi vuls/vuls +``` + +- vuls + +``` +$ docker rmi vuls/vuls +``` + +3. Pull new vuls docker images + +- go-cve-dictionary + +``` +$ docker pull vuls/go-cve-dictionary +``` + +- vuls -1. Locate ssh-keys of target servers in (vuls/setup/docker/conf/) -2. Create and adjust config.toml(vuls/setup/docker/conf/config.toml) to your environment - - ``` - [servers] +``` +$ docker pull vuls/vuls +``` + +4. Confirm your vuls version + +```console +$ docker run --rm vuls/go-cve-dictionary -v + +go-cve-dictionary v0.1.xxx xxxx +``` - [servers.172-31-4-82] - host = "172.31.4.82" - user = "ec2-user" - keyPath = "conf/id_rsa" - ``` +- vuls -## Fetch Vulnerability database +```console +$ docker run --rm vuls/vuls -v -- Fetch Vulnerability database from NVD - ``` - $ docker exec -t vuls scripts/fetch_nvd_all.sh - ``` +vuls v0.1.xxx xxxx +``` + + +# How to use this image -## Scan servers with Vuls-On-Docker +1. fetch nvd (vuls/go-cve-dictionary) +1. configuration (vuls/vuls) +1. prepare (vuls/vuls) +1. scan (vuls/vuls) +1. vulsrepo (vuls/vulsrepo) + +## Step1. Fetch NVD + +```console +$ for i in {2002..2016}; do \ + docker run --rm -it \ + -v $PWD:/vuls \ + -v $PWD/go-cve-dictionary-log:/var/log/vuls \ + vuls/go-cve-dictionary fetchnvd -years $i; \ + done +``` -- Use the embedded script to scan servers for vulsrepo(or run whatever with docker exec) +## Step2. Configuration - ``` - $ docker exec -t vuls vuls prepare -config=conf/config.toml - $ docker exec -t vuls scripts/scan_for_vulsrepo.sh - ``` +Create config.toml referring to [this](https://github.com/future-architect/vuls#configuration). -## See the results in a browser +```toml +[servers] +[servers.amazon] +host = "54.249.93.16" +port = "22" +user = "vuls-user" +keyPath = "/root/.ssh/id_rsa" # path to ssh private key in docker ``` -http://${Vuls_Host}/vulsrepo/ +  + +```console +$ docker run --rm \ + -v ~/.ssh:/root/.ssh:ro \ + -v $PWD:/vuls \ + -v $PWD/vuls-log:/var/log/vuls \ + vuls/vuls configtest \ + -config=./config.toml # path to config.toml in docker ``` -# Update modules +## Step3. Prepare + +```console +$ docker run --rm \ + -v ~/.ssh:/root/.ssh:ro \ + -v $PWD:/vuls \ + -v $PWD/vuls-log:/var/log/vuls \ + vuls/vuls prepare \ + -config=./config.toml # path to config.toml in docker +``` + +## Step4. Scan + +```console +$ docker run --rm -it \ + -v ~/.ssh:/root/.ssh:ro \ + -v $PWD:/vuls \ + -v $PWD/vuls-log:/var/log/vuls \ + -v /etc/localtime:/etc/localtime:ro \ + -e "TZ=Asia/Tokyo" \ + vuls/vuls scan \ + -cve-dictionary-dbpath=/vuls/cve.sqlite3 \ + -report-json \ + -config=./config.toml # path to config.toml in docker +``` + +## Step5. vulsrepo + +```console +$docker run -dt \ + -v $PWD:/vuls \ + -p 80:80 \ + vuls/vulsrepo +``` + +# User Feedback + +## Documentation + +Documentation for this image is stored in the [`docker/` directory]() of the [`future-architect/vuls` GitHub repo](https://github.com/future-architect/vuls). + +## Issues -- update vuls, go-cve-dictionary, vulsrepo - ``` - $ docker exec -t vuls scripts/update_modules.sh - ``` +If you have any problems with or questions about this image, please contact us through a [GitHub issue](https://github.com/future-architect/vuls/issues). -# Update Vulnerability database +## Contributing -- Fetch Vulnerability database from NVD - ``` - $ docker exec -t vuls scripts/fetch_nvd_last2y.sh - ``` +1. fork a repository: github.com/future-architect/vuls to github.com/you/repo +1. get original code: go get github.com/future-architect/vuls +1. work on original code +1. add remote to your repo: git remote add myfork https://github.com/you/repo.git +1. push your changes: git push myfork +1. create a new Pull Request diff --git a/setup/docker/conf/.gitkeep b/setup/docker/conf/.gitkeep deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/setup/docker/docker-compose.yml b/setup/docker/docker-compose.yml deleted file mode 100644 index cb749d1d40..0000000000 --- a/setup/docker/docker-compose.yml +++ /dev/null @@ -1,11 +0,0 @@ -version: '2' -services: - vuls: - container_name: vuls - build: ./dockerfile - image: vuls-docker:0.1 - volumes: - - ./conf:/opt/vuls/conf - ports: - - "80:80" - diff --git a/setup/docker/dockerfile/Dockerfile b/setup/docker/dockerfile/Dockerfile deleted file mode 100644 index 625658eb51..0000000000 --- a/setup/docker/dockerfile/Dockerfile +++ /dev/null @@ -1,73 +0,0 @@ -FROM buildpack-deps:jessie-scm - -# golang Install -RUN apt-get update && apt-get install -y --no-install-recommends \ - g++ \ - gcc \ - libc6-dev \ - make \ - curl \ - && rm -rf /var/lib/apt/lists/* - -ENV GOLANG_VERSION 1.6.2 -ENV GOLANG_DOWNLOAD_URL https://golang.org/dl/go$GOLANG_VERSION.linux-amd64.tar.gz -ENV GOLANG_DOWNLOAD_SHA256 e40c36ae71756198478624ed1bb4ce17597b3c19d243f3f0899bb5740d56212a - -RUN curl -fsSL "$GOLANG_DOWNLOAD_URL" -o golang.tar.gz \ - && echo "$GOLANG_DOWNLOAD_SHA256 golang.tar.gz" | sha256sum -c - \ - && tar -C /usr/local -xzf golang.tar.gz \ - && rm golang.tar.gz - -ENV GOPATH /go -ENV PATH $GOPATH/bin:/usr/local/go/bin:$PATH - -RUN mkdir -p "$GOPATH/src" "$GOPATH/bin" && chmod -R 777 "$GOPATH" - -# glide install -ENV GLIDE_VERSION 0.10.2 -ENV GLIDE_DOWNLOAD_URL https://github.com/Masterminds/glide/releases/download/$GLIDE_VERSION/glide-$GLIDE_VERSION-linux-amd64.tar.gz -RUN curl -fsSL "$GLIDE_DOWNLOAD_URL" -o glide.tar.gz \ - && mkdir /usr/local/glide \ - && tar -C /usr/local/glide -xzf glide.tar.gz \ - && ln -s /usr/local/glide/linux-amd64/glide /usr/local/bin/ \ - && rm glide.tar.gz - -#Vuls Install -ENV VULS_ROOT /opt/vuls -RUN mkdir -p /var/log/vuls ${VULS_ROOT}/conf /root/.ssh/ -RUN chmod 700 -R /var/log/vuls $VULS_ROOT -# RUN go get github.com/kotakanbe/go-cve-dictionary -# RUN go get github.com/future-architect/vuls - -RUN go get -v -d github.com/kotakanbe/go-cve-dictionary \ - && cd $GOPATH/src/github.com/kotakanbe/go-cve-dictionary \ - && glide install \ - && go install - -RUN go get -v -d github.com/future-architect/vuls \ - && cd $GOPATH/src/github.com/future-architect/vuls \ - && glide install \ - && go install - -# Copy custom Scripts -COPY ./scripts/ ${VULS_ROOT}/scripts -RUN chmod 755 ${VULS_ROOT}/scripts/* - - -#Vulrepo Install -RUN apt-get update \ - && apt-get install -y --no-install-recommends \ - apache2 \ - libcgi-pm-perl \ - libjson-perl \ - && rm -rf /var/lib/apt/lists/* \ - && cd /var/www/html/ \ - && git clone https://github.com/usiusi360/vulsrepo \ - && mkdir /var/www/html/vulsrepo/results \ - && cp /var/www/html/vulsrepo/dist/cgi/vulsrepo.conf.sample /etc/apache2/conf-enabled/vulsrepo.conf \ - && a2enmod cgid - -#Home -WORKDIR /opt/vuls -EXPOSE 80 443 -ENTRYPOINT service apache2 start && tail -f /dev/null diff --git a/setup/docker/dockerfile/scripts/fetch_jvn_all.sh b/setup/docker/dockerfile/scripts/fetch_jvn_all.sh deleted file mode 100644 index f738a10b45..0000000000 --- a/setup/docker/dockerfile/scripts/fetch_jvn_all.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash -VULS_ROOT=/opt/vuls -#VULS_CONF=${VULS_ROOT}/conf -cd $VULS_ROOT -for i in {2002..2016}; do go-cve-dictionary fetchjvn -years $i; done - diff --git a/setup/docker/dockerfile/scripts/fetch_jvn_last2y.sh b/setup/docker/dockerfile/scripts/fetch_jvn_last2y.sh deleted file mode 100644 index 62a0d992d9..0000000000 --- a/setup/docker/dockerfile/scripts/fetch_jvn_last2y.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash -VULS_ROOT=/opt/vuls -#VULS_CONF=${VULS_ROOT}/conf -cd $VULS_ROOT -go-cve-dictionary fetchjvn -last2y - diff --git a/setup/docker/dockerfile/scripts/fetch_jvn_latest.sh b/setup/docker/dockerfile/scripts/fetch_jvn_latest.sh deleted file mode 100644 index 66a5b36f80..0000000000 --- a/setup/docker/dockerfile/scripts/fetch_jvn_latest.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash -VULS_ROOT=/opt/vuls -#VULS_CONF=${VULS_ROOT}/conf -cd $VULS_ROOT -go-cve-dictionary fetchjvn -latest diff --git a/setup/docker/dockerfile/scripts/fetch_nvd_all.sh b/setup/docker/dockerfile/scripts/fetch_nvd_all.sh deleted file mode 100644 index fb9060d104..0000000000 --- a/setup/docker/dockerfile/scripts/fetch_nvd_all.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash -VULS_ROOT=/opt/vuls -#VULS_CONF=${VULS_ROOT}/conf -cd $VULS_ROOT -for i in {2002..2016}; do go-cve-dictionary fetchnvd -years $i; done - diff --git a/setup/docker/dockerfile/scripts/fetch_nvd_last2y.sh b/setup/docker/dockerfile/scripts/fetch_nvd_last2y.sh deleted file mode 100644 index 57a2955830..0000000000 --- a/setup/docker/dockerfile/scripts/fetch_nvd_last2y.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash -VULS_ROOT=/opt/vuls -#VULS_CONF=${VULS_ROOT}/conf -cd $VULS_ROOT -go-cve-dictionary fetchnvd -last2y - diff --git a/setup/docker/dockerfile/scripts/scan_for_vulsrepo.sh b/setup/docker/dockerfile/scripts/scan_for_vulsrepo.sh deleted file mode 100644 index c3c43161c2..0000000000 --- a/setup/docker/dockerfile/scripts/scan_for_vulsrepo.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash -VULS_ROOT=/opt/vuls -VULS_CONF=${VULS_ROOT}/conf -APACHE_VULSREPO_ROOT=/var/www/html/vulsrepo -cd $VULS_ROOT -vuls scan -report-json --cve-dictionary-dbpath=${VULS_ROOT}/cve.sqlite3 -config=${VULS_CONF}/config.toml -rm ${APACHE_VULSREPO_ROOT}/results/* -cp ${VULS_ROOT}/results/current/* ${APACHE_VULSREPO_ROOT}/results diff --git a/setup/docker/dockerfile/scripts/update_modules.sh b/setup/docker/dockerfile/scripts/update_modules.sh deleted file mode 100644 index 9cd3b493dd..0000000000 --- a/setup/docker/dockerfile/scripts/update_modules.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -cd $GOPATH/src/github.com/future-architect/vuls -git pull origin master -glide install -go install - - -cd $GOPATH/src/github.com/kotakanbe/go-cve-dictionary -git pull origin master -glide install -go install - - -cd /var/www/html/vulsrepo -git pull origin master diff --git a/setup/docker/go-cve-dictionary/latest/Dockerfile b/setup/docker/go-cve-dictionary/latest/Dockerfile new file mode 100644 index 0000000000..c201bec3ff --- /dev/null +++ b/setup/docker/go-cve-dictionary/latest/Dockerfile @@ -0,0 +1,19 @@ +FROM golang:latest + +MAINTAINER hikachan sadayuki-matsuno + +ENV REPOSITORY github.com/kotakanbe/go-cve-dictionary +ENV LOGDIR /var/log/vuls +ENV WORKDIR /vuls +# go-cve-dictionary install +RUN git clone https://$REPOSITORY.git $GOPATH/src/$REPOSITORY \ + && cd $GOPATH/src/$REPOSITORY \ + && make install \ + && mkdir -p $LOGDIR + +VOLUME [$WORKDIR, $LOGDIR] +WORKDIR $WORKDIR +ENV PWD $WORKDIR + +ENTRYPOINT ["go-cve-dictionary"] +CMD ["--help"] diff --git a/setup/docker/go-cve-dictionary/latest/README.md b/setup/docker/go-cve-dictionary/latest/README.md new file mode 100644 index 0000000000..588294ae8b --- /dev/null +++ b/setup/docker/go-cve-dictionary/latest/README.md @@ -0,0 +1,89 @@ +# go-cve-dictionary-Docker + +This is the Git repo of the official Docker image for go-cve-dictionary. +See the [Hub page](https://hub.docker.com/r/vuls/go-cve-dictionary/) for the full readme on how to use the Docker image and for information regarding contributing and issues. + +# Supported tags and respective `Dockerfile` links + +- [`latest` (*go-cve-dictionary:latest Dockerfile*)](https://github.com/future-architect/vuls/blob/master/setup/docker/go-cve-dictionary/latest/Dockerfile) + +# Caution + +This image is built per commit. +If you want to use the latest docker image, you should remove the existing image, and pull it once again. + +- Remove old docker image + +``` +$ docker rmi vuls/go-cve-dictionary +``` + +- Pull new docker image + +``` +$ docker pull vuls/go-cve-dictionary +``` + +# What is go-cve-dictionary? + +This is tool to build a local copy of the NVD (National Vulnerabilities Database) [1] and the Japanese JVN [2], which contain security vulnerabilities according to their CVE identifiers [3] including exhaustive information and a risk score. The local copy is generated in sqlite format, and the tool has a server mode for easy querying. + +[1] https://en.wikipedia.org/wiki/National_Vulnerability_Database +[2] https://en.wikipedia.org/wiki/Common_Vulnerabilities_and_Exposures +[3] http://jvndb.jvn.jp/apis/termsofuse.html + +# How to use this image + +## check vuls version + +``` +$ docker run --rm vuls/go-cve-dictionary -v +``` + +## fetchnvd + +```console +$ for i in {2002..2016}; do \ + docker run --rm -it \ + -v $PWD:/vuls \ + -v $PWD/go-cve-dictionary-log:/var/log/vuls \ + vuls/go-cve-dictionary fetchnvd -years $i; \ + done +``` + +## server + +```console +$ docker run -dt \ + --name go-cve-dictionary \ + -v $PWD:/vuls \ + -v $PWD/go-cve-dictionary-log:/var/log/vuls \ + --expose 1323 \ + -p 1323:1323 \ + vuls/go-cve-dictionary server --bind=0.0.0.0 +``` + +Prease refer to [this](https://hub.docker.com/r/vuls/go-cve-dictionary). + +## vuls + +Please refer to [this](https://hub.docker.com/r/vuls/vuls/). + +# User Feedback + +## Documentation + +Documentation for this image is stored in the [`docker/` directory](https://github.com/future-architect/vuls/tree/master/setup/docker) of the [`future-architect/vuls` GitHub repo](https://github.com/future-architect/vuls). + +## Issues + +If you have any problems with or questions about this image, please contact us through a [GitHub issue](https://github.com/future-architect/vuls/issues). + +## Contributing + +1. fork a repository: github.com/future-architect/vuls to github.com/you/repo +1. get original code: go get github.com/future-architect/vuls +1. work on original code +1. add remote to your repo: git remote add myfork https://github.com/you/repo.git +1. push your changes: git push myfork +1. create a new Pull Request diff --git a/setup/docker/vuls/latest/Dockerfile b/setup/docker/vuls/latest/Dockerfile new file mode 100644 index 0000000000..1db73c550f --- /dev/null +++ b/setup/docker/vuls/latest/Dockerfile @@ -0,0 +1,19 @@ +FROM golang:latest + +MAINTAINER hikachan sadayuki-matsuno + +ENV REPOSITORY github.com/future-architect/vuls +ENV LOGDIR /var/log/vuls +ENV WORKDIR /vuls +# go-cve-dictionary install +RUN git clone https://$REPOSITORY.git $GOPATH/src/$REPOSITORY \ + && cd $GOPATH/src/$REPOSITORY \ + && make install \ + && mkdir -p $LOGDIR + +VOLUME [$WORKDIR, $LOGDIR] +WORKDIR $WORKDIR +ENV PWD $WORKDIR + +ENTRYPOINT ["vuls"] +CMD ["--help"] diff --git a/setup/docker/vuls/latest/README.md b/setup/docker/vuls/latest/README.md new file mode 100644 index 0000000000..0fe862850e --- /dev/null +++ b/setup/docker/vuls/latest/README.md @@ -0,0 +1,121 @@ +# Vuls-Docker + +This is the Git repo of the official Docker image for vuls. +See the [Hub page](https://hub.docker.com/r/vuls/vuls/) for the full readme on how to use the Docker image and for information regarding contributing and issues. + +# Supported tags and respective `Dockerfile` links + +- [`latest` (*vuls:latest Dockerfile*)](https://github.com/future-architect/vuls/blob/master/setup/docker/vuls/latest/Dockerfile) + +# Caution + +This image is built per commit. +If you want to use the latest docker image, you should remove the existing image, and pull it once again. + +- Remove old docker image + +``` +$ docker rmi vuls/vuls +``` + +- Pull new docker image + +``` +$ docker pull vuls/vuls +``` + +# What is Vuls? + +Vuls is the Vulnerability scanner for Linux/FreeBSD, agentless, written in golang. +Please see the [Documentation](https://github.com/future-architect/vuls) + +![logo](https://github.com/future-architect/vuls/blob/master/img/vuls_logo.png?raw=true) + +# How to use this image + +## check vuls version + +``` +$ docker run --rm vuls/vuls -v +``` + +## configtest + +Create config.toml referring to [this](https://github.com/future-architect/vuls#configuration). + +```toml +[servers] + +[servers.amazon] +host = "54.249.93.16" +port = "22" +user = "vuls-user" +keyPath = "/root/.ssh/id_rsa" # path to ssh private key in docker +``` +  + +```console +$ docker run --rm \ + -v ~/.ssh:/root/.ssh:ro \ + -v $PWD:/vuls \ + -v $PWD/vuls-log:/var/log/vuls \ + vuls/vuls configtest +``` + + +## prepare + +```console +$ docker run --rm \ + -v ~/.ssh:/root/.ssh:ro \ + -v $PWD:/vuls \ + -v $PWD/vuls-log:/var/log/vuls \ + vuls/vuls prepare \ + -config=./config.toml # path to config.toml in docker +``` + +## scan + +```console +$ docker run --rm -it \ + -v ~/.ssh:/root/.ssh:ro \ + -v $PWD:/vuls \ + -v $PWD/vuls-log:/var/log/vuls \ + -v /etc/localtime:/etc/localtime:ro \ + vuls/vuls scan \ + -cve-dictionary-dbpath=/vuls/cve.sqlite3 \ + -config=./config.toml \ # path to config.toml in docker + -report-json +``` + +## tui + +```console +$ docker run --rm -it \ + -v $PWD:/vuls \ + -v $PWD/vuls-log:/var/log/vuls \ + vuls/vuls tui +``` + +## vulsrepo + +Prease refer to [this](https://hub.docker.com/r/vuls/vulsrepo/). + +# User Feedback + +## Documentation + +Documentation for this image is stored in the [`docker/` directory](https://github.com/future-architect/vuls/tree/master/setup/docker) of the [`future-architect/vuls` GitHub repo](https://github.com/future-architect/vuls). + +## Issues + +If you have any problems with or questions about this image, please contact us through a [GitHub issue](https://github.com/future-architect/vuls/issues). + +## Contributing + +1. fork a repository: github.com/future-architect/vuls to github.com/you/repo +1. get original code: go get github.com/future-architect/vuls +1. work on original code +1. add remote to your repo: git remote add myfork https://github.com/you/repo.git +1. push your changes: git push myfork +1. create a new Pull Request diff --git a/setup/docker/vulsrepo/latest/Dockerfile b/setup/docker/vulsrepo/latest/Dockerfile new file mode 100644 index 0000000000..8410553837 --- /dev/null +++ b/setup/docker/vulsrepo/latest/Dockerfile @@ -0,0 +1,31 @@ +FROM httpd:2.4 + +MAINTAINER hikachan sadayuki-matsuno +# install packages +RUN apt-get update \ + && apt-get install -y --no-install-recommends \ + ca-certificates \ + vim \ + git \ + libcgi-pm-perl \ + libjson-perl \ + && rm -r /var/lib/apt/lists/* + +# env +ENV HTTPD_PREFIX /usr/local/apache2 + +VOLUME /vuls + +WORKDIR ${HTTPD_PREFIX}/htdocs +RUN git clone https://github.com/usiusi360/vulsrepo.git \ + && echo "LoadModule cgid_module modules/mod_cgid.so" >> $HTTPD_PREFIX/conf/httpd.conf \ + && echo "" >> $HTTPD_PREFIX/conf/httpd.conf \ + && echo " Options +ExecCGI +FollowSymLinks" >> $HTTPD_PREFIX/conf/httpd.conf \ + && echo " AddHandler cgi-script cgi" >> $HTTPD_PREFIX/conf/httpd.conf \ + && echo "" >> $HTTPD_PREFIX/conf/httpd.conf \ + && sed -i -e 's/User daemon/#User/g' $HTTPD_PREFIX/conf/httpd.conf \ + && sed -i -e 's/Group daemon/#Group/g' $HTTPD_PREFIX/conf/httpd.conf \ + && ln -snf /vuls/results /usr/local/apache2/htdocs/vulsrepo/results + +EXPOSE 80 +CMD ["httpd-foreground"] diff --git a/setup/docker/vulsrepo/latest/README.md b/setup/docker/vulsrepo/latest/README.md new file mode 100644 index 0000000000..7b5ff687b6 --- /dev/null +++ b/setup/docker/vulsrepo/latest/README.md @@ -0,0 +1,47 @@ +# VulsRepo-Docker + +This is the Git repo of the official Docker image for vulsrepo. +See the [Hub page](https://hub.docker.com/r/vuls/vulsrepo/) for the full readme on how to use the Docker image and for information regarding contributing and issues. + +# Supported tags and respective `Dockerfile` links + +- [`latest` (*vulsrepo:latest Dockerfile*)](https://github.com/future-architect/vuls/blob/master/setup/docker/vulsrepo/latest/Dockerfile) + +# Caution + +This image is built per commit. +If you want to use the latest docker image, you should remove the existing image, and pull it once again. + +# What is vulsrepo? + +VulsRepo is visualized based on the json report output in [vuls](https://github.com/future-architect/vuls). + +# How to use this image + +## vulsrepo + +```console +$docker run -dt \ + -v $PWD:/vuls \ + -p 80:80 \ + vuls/vulsrepo +``` + +# User Feedback + +## Documentation + +Documentation for this image is stored in the [`docker/` directory](https://github.com/future-architect/vuls/tree/master/setup/docker) of the [`future-architect/vuls` GitHub repo](https://github.com/future-architect/vuls). + +## Issues + +If you have any problems with or questions about this image, please contact us through a [GitHub issue](https://github.com/future-architect/vuls/issues). + +## Contributing + +1. fork a repository: github.com/future-architect/vuls to github.com/you/repo +1. get original code: go get github.com/future-architect/vuls +1. work on original code +1. add remote to your repo: git remote add myfork https://github.com/you/repo.git +1. push your changes: git push myfork +1. create a new Pull Request diff --git a/version/version.go b/version/version.go deleted file mode 100644 index 3ba04ed2be..0000000000 --- a/version/version.go +++ /dev/null @@ -1,24 +0,0 @@ -/* Vuls - Vulnerability Scanner -Copyright (C) 2016 Future Architect, Inc. Japan. - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ - -package version - -// Name is Vuls -const Name string = "vuls" - -// Version of Vuls -const Version string = "0.1.6"