Compare commits
	
		
			106 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					a522218c4e | ||
| 
						 | 
					820455399c | ||
| 
						 | 
					959d612534 | ||
| 
						 | 
					cd81e6eab2 | ||
| 
						 | 
					e6ec6920ad | ||
| 
						 | 
					18a92fa1ca | ||
| 
						 | 
					f95af9897b | ||
| 
						 | 
					b61adcb1fd | ||
| 
						 | 
					1bbf320755 | ||
| 
						 | 
					159f26171c | ||
| 
						 | 
					8ac00f6c0d | ||
| 
						 | 
					ce2daf2493 | ||
| 
						 | 
					f014f8fd59 | ||
| 
						 | 
					f50a39a9e2 | ||
| 
						 | 
					e0d8147104 | ||
| 
						 | 
					c5cfac62da | ||
| 
						 | 
					83469ce5cc | ||
| 
						 | 
					7cd7b4a9a2 | ||
| 
						 | 
					7681b277cf | ||
| 
						 | 
					406efa96c0 | ||
| 
						 | 
					9a7a30c0bc | ||
| 
						 | 
					64bdfa0e80 | ||
| 
						 | 
					067089973c | ||
| 
						 | 
					85e6d753c7 | ||
| 
						 | 
					4094984642 | ||
| 
						 | 
					85c0009a43 | ||
| 
						 | 
					234e312ee2 | ||
| 
						 | 
					ce3ca64678 | ||
| 
						 | 
					b042a600c3 | ||
| 
						 | 
					686e9f07a9 | ||
| 
						 | 
					bb6725372b | ||
| 
						 | 
					6f012fc9c5 | ||
| 
						 | 
					4c82458481 | ||
| 
						 | 
					a0ac863998 | ||
| 
						 | 
					d23ef838f8 | ||
| 
						 | 
					f81ac197f5 | ||
| 
						 | 
					652b37e630 | ||
| 
						 | 
					c57e430393 | ||
| 
						 | 
					fff6047df9 | ||
| 
						 | 
					1e2b93d55b | ||
| 
						 | 
					66b27a7795 | ||
| 
						 | 
					63f0a272c4 | ||
| 
						 | 
					8d2180cf5a | ||
| 
						 | 
					1986f7e4dd | ||
| 
						 | 
					21beb396b4 | ||
| 
						 | 
					cb5a6f38d6 | ||
| 
						 | 
					67e4aaede0 | ||
| 
						 | 
					b42805d00c | ||
| 
						 | 
					95d6888c87 | ||
| 
						 | 
					549b315a65 | ||
| 
						 | 
					5b80b16684 | ||
| 
						 | 
					0cd0a4bf2b | ||
| 
						 | 
					b5cf06cad8 | ||
| 
						 | 
					b964d19d82 | ||
| 
						 | 
					cf7990d444 | ||
| 
						 | 
					738ccf7dbb | ||
| 
						 | 
					fc2ea48c1d | ||
| 
						 | 
					3af93b93d7 | ||
| 
						 | 
					f386c3be92 | ||
| 
						 | 
					239d910dbe | ||
| 
						 | 
					48929deabd | ||
| 
						 | 
					79523de1db | ||
| 
						 | 
					fbfc14dfeb | ||
| 
						 | 
					a8dc886f89 | ||
| 
						 | 
					cfc9e064b9 | ||
| 
						 | 
					e72fa3362a | ||
| 
						 | 
					26364421e8 | ||
| 
						 | 
					4a07974b54 | ||
| 
						 | 
					eaddc7f2ba | ||
| 
						 | 
					85056aaa00 | ||
| 
						 | 
					c077c740fa | ||
| 
						 | 
					c2eab87a3f | ||
| 
						 | 
					ea582d2d2e | ||
| 
						 | 
					2f89a24100 | ||
| 
						 | 
					73ebb94f67 | ||
| 
						 | 
					95bf387ecc | ||
| 
						 | 
					f17a8452f9 | ||
| 
						 | 
					920ffe1f33 | ||
| 
						 | 
					093bcb7477 | ||
| 
						 | 
					c06b3ec9eb | ||
| 
						 | 
					ac6fe6f9fc | ||
| 
						 | 
					2dffdaac42 | ||
| 
						 | 
					cb445c9504 | ||
| 
						 | 
					e3fc3aa9d1 | ||
| 
						 | 
					97c3f5d642 | ||
| 
						 | 
					0a52fc9a56 | ||
| 
						 | 
					c831339b0d | ||
| 
						 | 
					058ccf575f | ||
| 
						 | 
					92be12bc2f | ||
| 
						 | 
					1aa2f4b5b1 | ||
| 
						 | 
					bba9431985 | ||
| 
						 | 
					3c39f1e737 | ||
| 
						 | 
					e6f4d07a87 | ||
| 
						 | 
					e43358a0d2 | ||
| 
						 | 
					f0644e8a9d | ||
| 
						 | 
					11b010b281 | ||
| 
						 | 
					c751029127 | ||
| 
						 | 
					fb70d1b2f0 | ||
| 
						 | 
					3d68783b7f | ||
| 
						 | 
					0d77853912 | ||
| 
						 | 
					ea1b5dd8f7 | ||
| 
						 | 
					2dcb7d5ce1 | ||
| 
						 | 
					99cab34527 | ||
| 
						 | 
					f5eeed0bc2 | ||
| 
						 | 
					1b85e56961 | ||
| 
						 | 
					8a8ac5fd22 | 
							
								
								
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -2,7 +2,7 @@ vuls
 | 
			
		||||
.vscode
 | 
			
		||||
*.txt
 | 
			
		||||
*.json
 | 
			
		||||
*.sqlite3
 | 
			
		||||
*.sqlite3*
 | 
			
		||||
*.db
 | 
			
		||||
tags
 | 
			
		||||
.gitmodules
 | 
			
		||||
@@ -12,3 +12,4 @@ vendor/
 | 
			
		||||
log/
 | 
			
		||||
results/
 | 
			
		||||
*config.toml
 | 
			
		||||
!setup/docker/*
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										78
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										78
									
								
								CHANGELOG.md
									
									
									
									
									
								
							@@ -1,5 +1,83 @@
 | 
			
		||||
# Change Log
 | 
			
		||||
 | 
			
		||||
## [v0.1.7](https://github.com/future-architect/vuls/tree/v0.1.7) (2016-11-08)
 | 
			
		||||
[Full Changelog](https://github.com/future-architect/vuls/compare/v0.1.6...v0.1.7)
 | 
			
		||||
 | 
			
		||||
**Implemented enhancements:**
 | 
			
		||||
 | 
			
		||||
- Enable to scan only docker container, without docker host [\#122](https://github.com/future-architect/vuls/issues/122)
 | 
			
		||||
- Add -skip-broken option \[CentOS only\] \#245 [\#248](https://github.com/future-architect/vuls/pull/248) ([kotakanbe](https://github.com/kotakanbe))
 | 
			
		||||
- Display unknown CVEs to TUI [\#244](https://github.com/future-architect/vuls/pull/244) ([kotakanbe](https://github.com/kotakanbe))
 | 
			
		||||
- Add the XML output [\#240](https://github.com/future-architect/vuls/pull/240) ([gleentea](https://github.com/gleentea))
 | 
			
		||||
- add '-ssh-external' option to prepare subcommand [\#234](https://github.com/future-architect/vuls/pull/234) ([mykstmhr](https://github.com/mykstmhr))
 | 
			
		||||
- Integrate OWASP Dependency Check [\#232](https://github.com/future-architect/vuls/pull/232) ([kotakanbe](https://github.com/kotakanbe))
 | 
			
		||||
- Add support for reading CVE data from MySQL. [\#225](https://github.com/future-architect/vuls/pull/225) ([oswell](https://github.com/oswell))
 | 
			
		||||
- Remove base docker image, -v shows commit hash [\#223](https://github.com/future-architect/vuls/pull/223) ([sadayuki-matsuno](https://github.com/sadayuki-matsuno))
 | 
			
		||||
- Support ignore CveIDs in config [\#222](https://github.com/future-architect/vuls/pull/222) ([kotakanbe](https://github.com/kotakanbe))
 | 
			
		||||
- Confirm before installing dependencies on prepare [\#219](https://github.com/future-architect/vuls/pull/219) ([kotakanbe](https://github.com/kotakanbe))
 | 
			
		||||
- Remove all.json [\#218](https://github.com/future-architect/vuls/pull/218) ([kotakanbe](https://github.com/kotakanbe))
 | 
			
		||||
- Add GitHub issue template [\#217](https://github.com/future-architect/vuls/pull/217) ([kotakanbe](https://github.com/kotakanbe))
 | 
			
		||||
- Improve makefile, -version shows git hash, fix README [\#216](https://github.com/future-architect/vuls/pull/216) ([kotakanbe](https://github.com/kotakanbe))
 | 
			
		||||
- change e-mail package from gomail to net/smtp [\#211](https://github.com/future-architect/vuls/pull/211) ([sadayuki-matsuno](https://github.com/sadayuki-matsuno))
 | 
			
		||||
- Add only-containers option to scan subcommand \#122 [\#190](https://github.com/future-architect/vuls/pull/190) ([kotakanbe](https://github.com/kotakanbe))
 | 
			
		||||
- Fix -results-dir option of scan subcommand [\#185](https://github.com/future-architect/vuls/pull/185) ([kotakanbe](https://github.com/kotakanbe))
 | 
			
		||||
- Show error when no scannable servers are detected. [\#177](https://github.com/future-architect/vuls/pull/177) ([kotakanbe](https://github.com/kotakanbe))
 | 
			
		||||
- Add sudo check to prepare subcommand [\#176](https://github.com/future-architect/vuls/pull/176) ([kotakanbe](https://github.com/kotakanbe))
 | 
			
		||||
- Supports yum --enablerepo option \(supports only base,updates for now\) [\#147](https://github.com/future-architect/vuls/pull/147) ([kotakanbe](https://github.com/kotakanbe))
 | 
			
		||||
 | 
			
		||||
**Fixed bugs:**
 | 
			
		||||
 | 
			
		||||
- Debian 8.6 \(jessie\) scan does not show vulnerable packages [\#235](https://github.com/future-architect/vuls/issues/235)
 | 
			
		||||
- panic: runtime error: index out of range - ubuntu 16.04 + vuls history [\#180](https://github.com/future-architect/vuls/issues/180)
 | 
			
		||||
- Moved golang.org/x/net/context to context [\#243](https://github.com/future-architect/vuls/pull/243) ([yoheimuta](https://github.com/yoheimuta))
 | 
			
		||||
- Fix changelog cache bug on Ubuntu and Debian \#235 [\#238](https://github.com/future-architect/vuls/pull/238) ([kotakanbe](https://github.com/kotakanbe))
 | 
			
		||||
- add '-ssh-external' option to prepare subcommand [\#234](https://github.com/future-architect/vuls/pull/234) ([mykstmhr](https://github.com/mykstmhr))
 | 
			
		||||
- Fixed error for the latest version of gocui [\#231](https://github.com/future-architect/vuls/pull/231) ([ymd38](https://github.com/ymd38))
 | 
			
		||||
- Handle the refactored gocui SetCurrentView method. [\#229](https://github.com/future-architect/vuls/pull/229) ([oswell](https://github.com/oswell))
 | 
			
		||||
- Fix locale env var LANG to LANGUAGE [\#215](https://github.com/future-architect/vuls/pull/215) ([kotakanbe](https://github.com/kotakanbe))
 | 
			
		||||
- Fixed bug with parsing update line on CentOS/RHEL [\#206](https://github.com/future-architect/vuls/pull/206) ([andyone](https://github.com/andyone))
 | 
			
		||||
- Fix defer cache.DB.close [\#201](https://github.com/future-architect/vuls/pull/201) ([kotakanbe](https://github.com/kotakanbe))
 | 
			
		||||
- Fix a help message of -report-azure-blob option [\#195](https://github.com/future-architect/vuls/pull/195) ([kotakanbe](https://github.com/kotakanbe))
 | 
			
		||||
- Fix error handling in tui [\#193](https://github.com/future-architect/vuls/pull/193) ([kotakanbe](https://github.com/kotakanbe))
 | 
			
		||||
- Fix not working changelog cache on Container [\#189](https://github.com/future-architect/vuls/pull/189) ([kotakanbe](https://github.com/kotakanbe))
 | 
			
		||||
- Fix release version detection on FreeBSD [\#184](https://github.com/future-architect/vuls/pull/184) ([kotakanbe](https://github.com/kotakanbe))
 | 
			
		||||
- Fix defer cahce.DB.close\(\) [\#183](https://github.com/future-architect/vuls/pull/183) ([kotakanbe](https://github.com/kotakanbe))
 | 
			
		||||
- Fix a mode of files/dir \(report, log\) [\#182](https://github.com/future-architect/vuls/pull/182) ([kotakanbe](https://github.com/kotakanbe))
 | 
			
		||||
- Fix a error when no json dirs are found under results \#180 [\#181](https://github.com/future-architect/vuls/pull/181) ([kotakanbe](https://github.com/kotakanbe))
 | 
			
		||||
- ssh-external option of configtest is not working \#178 [\#179](https://github.com/future-architect/vuls/pull/179) ([kotakanbe](https://github.com/kotakanbe))
 | 
			
		||||
 | 
			
		||||
**Closed issues:**
 | 
			
		||||
 | 
			
		||||
- Recent changes to gobui cause build failures [\#228](https://github.com/future-architect/vuls/issues/228)
 | 
			
		||||
- https://hub.docker.com/r/vuls/go-cve-dictionary/ is empty [\#208](https://github.com/future-architect/vuls/issues/208)
 | 
			
		||||
- Not able to install gomail fails [\#202](https://github.com/future-architect/vuls/issues/202)
 | 
			
		||||
- No results file created - vuls tui failed [\#199](https://github.com/future-architect/vuls/issues/199)
 | 
			
		||||
- Wrong file permissions for results/\*.json in official Docker container [\#197](https://github.com/future-architect/vuls/issues/197)
 | 
			
		||||
- Failed: Unknown OS Type [\#196](https://github.com/future-architect/vuls/issues/196)
 | 
			
		||||
- Segmentation fault with configtest [\#192](https://github.com/future-architect/vuls/issues/192)
 | 
			
		||||
- Failed to scan. err: No server defined. Check the configuration [\#187](https://github.com/future-architect/vuls/issues/187)
 | 
			
		||||
- vuls configtest -ssh-external doesnt work [\#178](https://github.com/future-architect/vuls/issues/178)
 | 
			
		||||
- apt-get update: time out [\#175](https://github.com/future-architect/vuls/issues/175)
 | 
			
		||||
- scanning on Centos6, but vuls recognizes debian. [\#174](https://github.com/future-architect/vuls/issues/174)
 | 
			
		||||
 | 
			
		||||
**Merged pull requests:**
 | 
			
		||||
 | 
			
		||||
- Update README \#225 [\#242](https://github.com/future-architect/vuls/pull/242) ([kotakanbe](https://github.com/kotakanbe))
 | 
			
		||||
- fix readme [\#241](https://github.com/future-architect/vuls/pull/241) ([sadayuki-matsuno](https://github.com/sadayuki-matsuno))
 | 
			
		||||
- Fix README \#234 [\#237](https://github.com/future-architect/vuls/pull/237) ([kotakanbe](https://github.com/kotakanbe))
 | 
			
		||||
- Update glide files [\#236](https://github.com/future-architect/vuls/pull/236) ([kotakanbe](https://github.com/kotakanbe))
 | 
			
		||||
- fix README [\#226](https://github.com/future-architect/vuls/pull/226) ([usiusi360](https://github.com/usiusi360))
 | 
			
		||||
- fix some misspelling. [\#221](https://github.com/future-architect/vuls/pull/221) ([ymomoi](https://github.com/ymomoi))
 | 
			
		||||
- fix docker readme [\#214](https://github.com/future-architect/vuls/pull/214) ([sadayuki-matsuno](https://github.com/sadayuki-matsuno))
 | 
			
		||||
- Fix ja document about typo [\#213](https://github.com/future-architect/vuls/pull/213) ([shokohara](https://github.com/shokohara))
 | 
			
		||||
- fix readme [\#212](https://github.com/future-architect/vuls/pull/212) ([sadayuki-matsuno](https://github.com/sadayuki-matsuno))
 | 
			
		||||
- fix README [\#207](https://github.com/future-architect/vuls/pull/207) ([sadayuki-matsuno](https://github.com/sadayuki-matsuno))
 | 
			
		||||
- fix typo [\#204](https://github.com/future-architect/vuls/pull/204) ([usiusi360](https://github.com/usiusi360))
 | 
			
		||||
- fix gitignore [\#191](https://github.com/future-architect/vuls/pull/191) ([sadayuki-matsuno](https://github.com/sadayuki-matsuno))
 | 
			
		||||
- Update glide.lock [\#188](https://github.com/future-architect/vuls/pull/188) ([kotakanbe](https://github.com/kotakanbe))
 | 
			
		||||
- Fix path in setup/docker/README [\#186](https://github.com/future-architect/vuls/pull/186) ([dladuke](https://github.com/dladuke))
 | 
			
		||||
- Vuls and vulsrepo are now separated [\#163](https://github.com/future-architect/vuls/pull/163) ([hikachan](https://github.com/hikachan))
 | 
			
		||||
 | 
			
		||||
## [v0.1.6](https://github.com/future-architect/vuls/tree/v0.1.6) (2016-09-12)
 | 
			
		||||
[Full Changelog](https://github.com/future-architect/vuls/compare/v0.1.5...v0.1.6)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										36
									
								
								ISSUE_TEMPLATE
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								ISSUE_TEMPLATE
									
									
									
									
									
										Normal file
									
								
							@@ -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
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										28
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										28
									
								
								Makefile
									
									
									
									
									
								
							@@ -1,4 +1,9 @@
 | 
			
		||||
.PHONY: \
 | 
			
		||||
	glide \
 | 
			
		||||
	deps \
 | 
			
		||||
	update \
 | 
			
		||||
	build \
 | 
			
		||||
	install \
 | 
			
		||||
	all \
 | 
			
		||||
	vendor \
 | 
			
		||||
	lint \
 | 
			
		||||
@@ -12,13 +17,28 @@
 | 
			
		||||
 | 
			
		||||
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)'
 | 
			
		||||
 | 
			
		||||
glide:
 | 
			
		||||
	go get github.com/Masterminds/glide
 | 
			
		||||
 | 
			
		||||
deps: glide
 | 
			
		||||
	glide install
 | 
			
		||||
 | 
			
		||||
update: glide
 | 
			
		||||
	glide update
 | 
			
		||||
 | 
			
		||||
build: main.go deps
 | 
			
		||||
	go build -ldflags "$(LDFLAGS)" -o vuls $<
 | 
			
		||||
 | 
			
		||||
install: main.go deps
 | 
			
		||||
	go install -ldflags "$(LDFLAGS)"
 | 
			
		||||
 | 
			
		||||
all: test
 | 
			
		||||
 | 
			
		||||
#  vendor:
 | 
			
		||||
#          @ go get -v github.com/mjibson/party
 | 
			
		||||
#          party -d external -c -u
 | 
			
		||||
 | 
			
		||||
lint:
 | 
			
		||||
	@ go get -v github.com/golang/lint/golint
 | 
			
		||||
	$(foreach file,$(SRCS),golint $(file) || exit;)
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										308
									
								
								README.ja.md
									
									
									
									
									
								
							
							
						
						
									
										308
									
								
								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 clone 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
 | 
			
		||||
@@ -288,14 +284,13 @@ $ vuls tui
 | 
			
		||||
- NVDとJVN(日本語)から脆弱性データベースを取得し、SQLite3に格納する。
 | 
			
		||||
 | 
			
		||||
## Vuls
 | 
			
		||||

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

 | 
			
		||||
 | 
			
		||||
----
 | 
			
		||||
# Performance Considerations
 | 
			
		||||
@@ -376,7 +371,7 @@ notifyUsers  = ["@username"]
 | 
			
		||||
 | 
			
		||||
[mail]
 | 
			
		||||
smtpAddr      = "smtp.gmail.com"
 | 
			
		||||
smtpPort      = "465"
 | 
			
		||||
smtpPort      = "587"
 | 
			
		||||
user          = "username"
 | 
			
		||||
password      = "password"
 | 
			
		||||
from          = "from@address.com"
 | 
			
		||||
@@ -429,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`チャネルに送信される。スキャン前にチャネルを作成する必要がある。
 | 
			
		||||
@@ -457,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"
 | 
			
		||||
@@ -476,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"],
 | 
			
		||||
    #]
 | 
			
		||||
@@ -495,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"],
 | 
			
		||||
    #]
 | 
			
		||||
@@ -509,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レポートに含めたい追加情報
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -564,7 +562,7 @@ vuls ALL=(root) NOPASSWD: /usr/bin/apt-get, /usr/bin/apt-cache
 | 
			
		||||
 | 
			
		||||
# Usage: Prepare
 | 
			
		||||
 | 
			
		||||
Prepareサブコマンドは、Vuls内部で利用する以下のパッケージをスキャン対象サーバにインストーする。
 | 
			
		||||
Prepareサブコマンドは、Vuls内部で利用する以下のパッケージをスキャン対象サーバにインストールする。
 | 
			
		||||
 | 
			
		||||
| Distribution|            Release | Requirements |
 | 
			
		||||
|:------------|-------------------:|:-------------|
 | 
			
		||||
@@ -579,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
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
----
 | 
			
		||||
@@ -603,18 +606,22 @@ 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]
 | 
			
		||||
                [-ignore-unscored-cves]
 | 
			
		||||
                [-ssh-external]
 | 
			
		||||
                [-containers-only]
 | 
			
		||||
                [-skip-broken]
 | 
			
		||||
                [-report-azure-blob]
 | 
			
		||||
                [-report-json]
 | 
			
		||||
                [-report-mail]
 | 
			
		||||
                [-report-s3]
 | 
			
		||||
                [-report-slack]
 | 
			
		||||
                [-report-text]
 | 
			
		||||
                [-report-xml]
 | 
			
		||||
                [-http-proxy=http://192.168.0.1:8080]
 | 
			
		||||
                [-ask-key-password]
 | 
			
		||||
                [-debug]
 | 
			
		||||
@@ -646,8 +653,12 @@ scan:
 | 
			
		||||
        /path/to/cache.db (local cache of changelog for Ubuntu/Debian) (default "$PWD/cache.db")
 | 
			
		||||
  -config string
 | 
			
		||||
        /path/to/toml (default "$PWD/config.toml")
 | 
			
		||||
  -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
 | 
			
		||||
@@ -672,8 +683,12 @@ scan:
 | 
			
		||||
        Send report via Slack
 | 
			
		||||
  -report-text
 | 
			
		||||
        Write report to text files ($PWD/results/current)
 | 
			
		||||
  -report-xml
 | 
			
		||||
        Write report to XML files ($PWDresults/current)
 | 
			
		||||
  -results-dir string
 | 
			
		||||
        /path/to/results (default "$PWD/results")
 | 
			
		||||
  -skip-broken
 | 
			
		||||
        [For CentOS] yum update changelog with --skip-broken option
 | 
			
		||||
  -ssh-external
 | 
			
		||||
        Use external ssh command. Default: Use the Go native implementation
 | 
			
		||||
```
 | 
			
		||||
@@ -699,11 +714,10 @@ Defaults:vuls !requiretty
 | 
			
		||||
| empty password   |                 -  | |
 | 
			
		||||
| with password    |           required | or use ssh-agent |
 | 
			
		||||
 | 
			
		||||
## -report-json , -report-text option
 | 
			
		||||
## -report-json , -report-text , -report-xml option
 | 
			
		||||
 | 
			
		||||
結果をファイルに出力したい場合に指定する。出力先は、`$PWD/result/current/`    
 | 
			
		||||
`all.(json|txt)`には、全サーバのスキャン結果が出力される。  
 | 
			
		||||
`servername.(json|txt)`には、サーバごとのスキャン結果が出力される。
 | 
			
		||||
`servername.(json|txt|xml)`には、サーバごとのスキャン結果が出力される。
 | 
			
		||||
 | 
			
		||||
## Example: Scan all servers defined in config file
 | 
			
		||||
```
 | 
			
		||||
@@ -786,6 +800,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に含めることができる。  
 | 
			
		||||
@@ -826,11 +877,19 @@ 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
 | 
			
		||||
 | 
			
		||||
Vulsは、[CPE](https://nvd.nist.gov/cpe.cfm)に登録されているソフトウェアであれば、OSパッケージ以外のソフトウェアの脆弱性もスキャン可能。
 | 
			
		||||
Vulsは、[CPE](https://nvd.nist.gov/cpe.cfm)に登録されているソフトウェアであれば、OSパッケージ以外のソフトウェアの脆弱性もスキャン可能。  
 | 
			
		||||
たとえば、自分でコンパイルしたものや、言語のライブラリ、フレームワークなど。
 | 
			
		||||
 | 
			
		||||
-  CPEの検索方法
 | 
			
		||||
@@ -853,13 +912,38 @@ 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
 | 
			
		||||
 | 
			
		||||
DockerコンテナはSSHデーモンを起動しないで運用するケースが一般的。  
 | 
			
		||||
 [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は、DockerホストにSSHで接続し、`docker exec`でDockerコンテナにコマンドを発行して脆弱性をスキャンする。
 | 
			
		||||
Vulsは、DockerホストにSSHで接続し、`docker exec`でDockerコンテナにコマンドを発行して脆弱性をスキャンする。  
 | 
			
		||||
詳細は、[Architecture section](https://github.com/future-architect/vuls#architecture)を参照
 | 
			
		||||
 | 
			
		||||
- 全ての起動中のDockerコンテナをスキャン  
 | 
			
		||||
@@ -874,10 +958,10 @@ Vulsは、DockerホストにSSHで接続し、`docker exec`でDockerコンテナ
 | 
			
		||||
    containers = ["${running}"]
 | 
			
		||||
    ```
 | 
			
		||||
 | 
			
		||||
- あるコンテナのみスキャン
 | 
			
		||||
  コンテナID、または、コンテナ名を、containersに指定する。
 | 
			
		||||
  以下の例では、`container_name_a`と、`4aa37a8b63b9`のコンテナのみスキャンする
 | 
			
		||||
  スキャン実行前に、コンテナが起動中か確認すること。もし起動してない場合はエラーメッセージを出力してスキャンを中断する。
 | 
			
		||||
- あるコンテナのみスキャン  
 | 
			
		||||
  コンテナID、または、コンテナ名を、containersに指定する。  
 | 
			
		||||
  以下の例では、`container_name_a`と、`4aa37a8b63b9`のコンテナのみスキャンする  
 | 
			
		||||
  スキャン実行前に、コンテナが起動中か確認すること。もし起動してない場合はエラーメッセージを出力してスキャンを中断する。  
 | 
			
		||||
    ```
 | 
			
		||||
    [servers]
 | 
			
		||||
 | 
			
		||||
@@ -887,6 +971,9 @@ Vulsは、DockerホストにSSHで接続し、`docker exec`でDockerコンテナ
 | 
			
		||||
    keyPath     = "/home/username/.ssh/id_rsa"
 | 
			
		||||
    containers = ["container_name_a", "4aa37a8b63b9"]
 | 
			
		||||
    ```
 | 
			
		||||
- コンテナのみをスキャンする場合(ホストはスキャンしない)  
 | 
			
		||||
  --containers-onlyオプションを指定する
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Usage: TUI
 | 
			
		||||
 | 
			
		||||
@@ -904,14 +991,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
 | 
			
		||||
 | 
			
		||||
@@ -957,89 +1044,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]
 | 
			
		||||
see [go-cve-dictionary#usage-fetch-jvn-data](https://github.com/kotakanbe/go-cve-dictionary#usage-fetch-jvn-data)
 | 
			
		||||
 | 
			
		||||
      -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.
 | 
			
		||||
 | 
			
		||||
    ```
 | 
			
		||||
 | 
			
		||||
- すべての期間の脆弱性情報を取得(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の実行順序の注意
 | 
			
		||||
 | 
			
		||||
@@ -1070,47 +1082,25 @@ 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
 | 
			
		||||
- Update go-cve-dictionary  
 | 
			
		||||
If the DB schema was changed, please specify new SQLite3 or MySQL DB file.
 | 
			
		||||
```
 | 
			
		||||
$ cd $GOPATH/src/github.com/kotakanbe/go-cve-dictionary
 | 
			
		||||
$ git pull
 | 
			
		||||
$ 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
 | 
			
		||||
```
 | 
			
		||||
- The binaries are created under $GOPARH/bin
 | 
			
		||||
- If the DB schema was changed, please specify new SQLite3 DB file.
 | 
			
		||||
- バイナリファイルは`$GOPARH/bin`以下に作成される
 | 
			
		||||
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
@@ -1130,12 +1120,12 @@ Use Systemd, Upstart or supervisord, daemontools...
 | 
			
		||||
CRONなどを使えば可能
 | 
			
		||||
 | 
			
		||||
- 自動定期スキャン  
 | 
			
		||||
CRONなどを使い、自動化のためにsudoと、秘密鍵のパスワードなしでも実行可能なようにする
 | 
			
		||||
CRONなどを使い、自動化のためにsudoと、秘密鍵のパスワードなしでも実行可能なようにする  
 | 
			
		||||
  - スキャン対象サーバの /etc/sudoers に NOPASSWORD を設定する  
 | 
			
		||||
  - 秘密鍵パスフレーズなしの公開鍵認証か、ssh-agentを使う  
 | 
			
		||||
 | 
			
		||||
- スキャンが重く感じる
 | 
			
		||||
vulsのスキャン対象に脆弱性が溜まりすぎると実行時間が長くなります
 | 
			
		||||
- スキャンが重く感じる  
 | 
			
		||||
vulsのスキャン対象に脆弱性が溜まりすぎると実行時間が長くなります 
 | 
			
		||||
脆弱性のある状態は溜めすぎないようにしましょう
 | 
			
		||||
 | 
			
		||||
- クロスコンパイル
 | 
			
		||||
@@ -1205,7 +1195,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).
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										257
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										257
									
								
								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,17 +284,15 @@ see https://github.com/future-architect/vuls/tree/master/setup/docker
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
## [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.
 | 
			
		||||
 | 
			
		||||
## Vuls
 | 
			
		||||
## Scanning Flow
 | 
			
		||||

 | 
			
		||||
- Scan vulnerabilities on the servers via SSH and create a list of the CVE ID
 | 
			
		||||
  - To scan Docker containers, Vuls connect via ssh to the Docker host and then `docker exec` to the containers. So, no need to run sshd daemon on the containers.
 | 
			
		||||
- Fetch more detailed information of the detected CVE from go-cve-dictionary
 | 
			
		||||
- Insert scan result into SQLite3
 | 
			
		||||
- Send a report by Slack and Email
 | 
			
		||||
- Show the latest report on your terminal
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
- Write scan results to JSON file to show the latest report on your terminal 
 | 
			
		||||
 | 
			
		||||
----
 | 
			
		||||
# Performance Considerations
 | 
			
		||||
@@ -375,7 +375,7 @@ notifyUsers  = ["@username"]
 | 
			
		||||
 | 
			
		||||
[mail]
 | 
			
		||||
smtpAddr      = "smtp.gmail.com"
 | 
			
		||||
smtpPort      = "465"
 | 
			
		||||
smtpPort      = "587"
 | 
			
		||||
user          = "username"
 | 
			
		||||
password      = "password"
 | 
			
		||||
from          = "from@address.com"
 | 
			
		||||
@@ -391,6 +391,7 @@ subjectPrefix = "[vuls]"
 | 
			
		||||
#  "cpe:/a:rubyonrails:ruby_on_rails:4.2.1",
 | 
			
		||||
#]
 | 
			
		||||
#containers = ["${running}"]
 | 
			
		||||
#ignoreCves = ["CVE-2016-6313"]
 | 
			
		||||
#optional = [
 | 
			
		||||
#    ["key", "value"],
 | 
			
		||||
#]
 | 
			
		||||
@@ -406,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"],
 | 
			
		||||
#]
 | 
			
		||||
@@ -428,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`.  
 | 
			
		||||
@@ -459,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"
 | 
			
		||||
@@ -478,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"],
 | 
			
		||||
    #]
 | 
			
		||||
@@ -497,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"],
 | 
			
		||||
    #]
 | 
			
		||||
@@ -510,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)
 | 
			
		||||
@@ -578,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
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
----
 | 
			
		||||
@@ -603,18 +613,22 @@ 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]
 | 
			
		||||
                [-ignore-unscored-cves]
 | 
			
		||||
                [-ssh-external]
 | 
			
		||||
                [-containers-only]
 | 
			
		||||
                [-skip-broken]
 | 
			
		||||
                [-report-azure-blob]
 | 
			
		||||
                [-report-json]
 | 
			
		||||
                [-report-mail]
 | 
			
		||||
                [-report-s3]
 | 
			
		||||
                [-report-slack]
 | 
			
		||||
                [-report-text]
 | 
			
		||||
                [-report-xml]
 | 
			
		||||
                [-http-proxy=http://192.168.0.1:8080]
 | 
			
		||||
                [-ask-key-password]
 | 
			
		||||
                [-debug]
 | 
			
		||||
@@ -646,8 +660,12 @@ scan:
 | 
			
		||||
        /path/to/cache.db (local cache of changelog for Ubuntu/Debian) (default "$PWD/cache.db")
 | 
			
		||||
  -config string
 | 
			
		||||
        /path/to/toml (default "$PWD/config.toml")
 | 
			
		||||
  -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
 | 
			
		||||
@@ -672,8 +690,12 @@ scan:
 | 
			
		||||
        Send report via Slack
 | 
			
		||||
  -report-text
 | 
			
		||||
        Write report to text files ($PWD/results/current)
 | 
			
		||||
  -report-xml
 | 
			
		||||
        Write report to XML files ($PWDresults/current)
 | 
			
		||||
  -results-dir string
 | 
			
		||||
        /path/to/results (default "$PWD/results")
 | 
			
		||||
  -skip-broken
 | 
			
		||||
        [For CentOS] yum update changelog with --skip-broken option
 | 
			
		||||
  -ssh-external
 | 
			
		||||
        Use external ssh command. Default: Use the Go native implementation
 | 
			
		||||
```
 | 
			
		||||
@@ -682,11 +704,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
 | 
			
		||||
@@ -700,10 +722,10 @@ Defaults:vuls !requiretty
 | 
			
		||||
| empty password   |                 -  | |
 | 
			
		||||
| with password    |           required | or use ssh-agent |
 | 
			
		||||
 | 
			
		||||
## -report-json , -report-text option
 | 
			
		||||
## -report-json , -report-text , -report-xml 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.
 | 
			
		||||
`servername.(json|txt|xml)` includes the scan result of the server.
 | 
			
		||||
 | 
			
		||||
## Example: Scan all servers defined in config file
 | 
			
		||||
```
 | 
			
		||||
@@ -715,7 +737,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
 | 
			
		||||
@@ -779,6 +801,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.  
 | 
			
		||||
@@ -819,9 +878,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).
 | 
			
		||||
 | 
			
		||||
@@ -830,10 +897,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]
 | 
			
		||||
 | 
			
		||||
@@ -845,10 +912,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.  
 | 
			
		||||
@@ -880,6 +971,9 @@ For more details, see [Architecture section](https://github.com/future-architect
 | 
			
		||||
    keyPath     = "/home/username/.ssh/id_rsa"
 | 
			
		||||
    containers = ["container_name_a", "4aa37a8b63b9"]
 | 
			
		||||
    ```
 | 
			
		||||
- To scan containers only
 | 
			
		||||
  - --containers-only option is available.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Usage: TUI
 | 
			
		||||
 | 
			
		||||
@@ -897,14 +991,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
 | 
			
		||||
 | 
			
		||||
@@ -950,80 +1044,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]
 | 
			
		||||
see [go-cve-dictionary#usage-fetch-nvd-data](https://github.com/kotakanbe/go-cve-dictionary#usage-fetch-nvd-data)
 | 
			
		||||
 | 
			
		||||
  -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
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
- Update go-cve-dictionary  
 | 
			
		||||
If the DB schema was changed, please specify new SQLite3 or MySQL DB file.
 | 
			
		||||
```
 | 
			
		||||
$ cd $GOPATH/src/github.com/kotakanbe/go-cve-dictionary
 | 
			
		||||
$ git pull
 | 
			
		||||
$ 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
 | 
			
		||||
```
 | 
			
		||||
- The binaries are created under $GOPARH/bin
 | 
			
		||||
- If the DB schema was changed, please specify new SQLite3 DB file.
 | 
			
		||||
Binary file was built under $GOPARH/bin
 | 
			
		||||
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
@@ -1039,7 +1083,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.  
 | 
			
		||||
@@ -1114,7 +1158,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).
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -18,6 +18,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
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"
 | 
			
		||||
@@ -97,6 +97,7 @@ func (p *ConfigtestCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interfa
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	c.Conf.Debug = p.debug
 | 
			
		||||
	c.Conf.SSHExternal = p.sshExternal
 | 
			
		||||
 | 
			
		||||
	err = c.Load(p.configPath, keyPass)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
@@ -150,7 +151,10 @@ func (p *ConfigtestCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interfa
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Log.Info("Detecting Server/Contianer OS... ")
 | 
			
		||||
	scan.InitServers(Log)
 | 
			
		||||
	if err := scan.InitServers(Log); err != nil {
 | 
			
		||||
		Log.Errorf("Failed to init servers: %s", err)
 | 
			
		||||
		return subcommands.ExitFailure
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Log.Info("Checking sudo configuration... ")
 | 
			
		||||
	if err := scan.CheckIfSudoNoPasswd(Log); err != nil {
 | 
			
		||||
 
 | 
			
		||||
@@ -18,6 +18,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
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"],
 | 
			
		||||
#]
 | 
			
		||||
 
 | 
			
		||||
@@ -18,6 +18,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
package commands
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"flag"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
@@ -28,14 +29,13 @@ 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
 | 
			
		||||
type HistoryCmd struct {
 | 
			
		||||
	debug       bool
 | 
			
		||||
	debugSQL    bool
 | 
			
		||||
	jsonBaseDir string
 | 
			
		||||
	debug      bool
 | 
			
		||||
	debugSQL   bool
 | 
			
		||||
	resultsDir string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Name return subcommand name
 | 
			
		||||
@@ -59,15 +59,15 @@ func (p *HistoryCmd) SetFlags(f *flag.FlagSet) {
 | 
			
		||||
	f.BoolVar(&p.debugSQL, "debug-sql", false, "SQL debug mode")
 | 
			
		||||
 | 
			
		||||
	wd, _ := os.Getwd()
 | 
			
		||||
	defaultJSONBaseDir := filepath.Join(wd, "results")
 | 
			
		||||
	f.StringVar(&p.jsonBaseDir, "results-dir", defaultJSONBaseDir, "/path/to/results")
 | 
			
		||||
	defaultResultsDir := filepath.Join(wd, "results")
 | 
			
		||||
	f.StringVar(&p.resultsDir, "results-dir", defaultResultsDir, "/path/to/results")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Execute execute
 | 
			
		||||
func (p *HistoryCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
 | 
			
		||||
 | 
			
		||||
	c.Conf.DebugSQL = p.debugSQL
 | 
			
		||||
	c.Conf.JSONBaseDir = p.jsonBaseDir
 | 
			
		||||
	c.Conf.ResultsDir = p.resultsDir
 | 
			
		||||
 | 
			
		||||
	var err error
 | 
			
		||||
	var jsonDirs report.JSONDirs
 | 
			
		||||
@@ -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
 | 
			
		||||
			}
 | 
			
		||||
 
 | 
			
		||||
@@ -18,6 +18,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
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,21 +143,29 @@ 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{})
 | 
			
		||||
 | 
			
		||||
	logger.Info("Detecting OS... ")
 | 
			
		||||
	scan.InitServers(logger)
 | 
			
		||||
	if err := scan.InitServers(logger); err != nil {
 | 
			
		||||
		logger.Errorf("Failed to init servers: %s", err)
 | 
			
		||||
		return subcommands.ExitFailure
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	logger.Info("Checking sudo configuration... ")
 | 
			
		||||
	if err := scan.CheckIfSudoNoPasswd(logger); err != nil {
 | 
			
		||||
		logger.Errorf("Failed to sudo with nopassword via SSH. Define NOPASSWD in /etc/sudoers on target servers")
 | 
			
		||||
		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
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	logger.Info("Success")
 | 
			
		||||
	return subcommands.ExitSuccess
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -18,6 +18,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
package commands
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"flag"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
@@ -33,7 +34,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
 | 
			
		||||
@@ -44,7 +45,8 @@ type ScanCmd struct {
 | 
			
		||||
 | 
			
		||||
	configPath string
 | 
			
		||||
 | 
			
		||||
	jsonBaseDir      string
 | 
			
		||||
	resultsDir       string
 | 
			
		||||
	cvedbtype        string
 | 
			
		||||
	cvedbpath        string
 | 
			
		||||
	cveDictionaryURL string
 | 
			
		||||
	cacheDBPath      string
 | 
			
		||||
@@ -56,6 +58,9 @@ type ScanCmd struct {
 | 
			
		||||
	askSudoPassword bool
 | 
			
		||||
	askKeyPassword  bool
 | 
			
		||||
 | 
			
		||||
	containersOnly bool
 | 
			
		||||
	skipBroken     bool
 | 
			
		||||
 | 
			
		||||
	// reporting
 | 
			
		||||
	reportSlack     bool
 | 
			
		||||
	reportMail      bool
 | 
			
		||||
@@ -63,6 +68,7 @@ type ScanCmd struct {
 | 
			
		||||
	reportText      bool
 | 
			
		||||
	reportS3        bool
 | 
			
		||||
	reportAzureBlob bool
 | 
			
		||||
	reportXML       bool
 | 
			
		||||
 | 
			
		||||
	awsProfile  string
 | 
			
		||||
	awsS3Bucket string
 | 
			
		||||
@@ -88,18 +94,22 @@ 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]
 | 
			
		||||
		[-ignore-unscored-cves]
 | 
			
		||||
		[-ssh-external]
 | 
			
		||||
		[-containers-only]
 | 
			
		||||
		[-skip-broken]
 | 
			
		||||
		[-report-azure-blob]
 | 
			
		||||
		[-report-json]
 | 
			
		||||
		[-report-mail]
 | 
			
		||||
		[-report-s3]
 | 
			
		||||
		[-report-slack]
 | 
			
		||||
		[-report-text]
 | 
			
		||||
		[-report-xml]
 | 
			
		||||
		[-http-proxy=http://192.168.0.1:8080]
 | 
			
		||||
		[-ask-key-password]
 | 
			
		||||
		[-debug]
 | 
			
		||||
@@ -126,8 +136,14 @@ func (p *ScanCmd) SetFlags(f *flag.FlagSet) {
 | 
			
		||||
	defaultConfPath := filepath.Join(wd, "config.toml")
 | 
			
		||||
	f.StringVar(&p.configPath, "config", defaultConfPath, "/path/to/toml")
 | 
			
		||||
 | 
			
		||||
	defaultJSONBaseDir := filepath.Join(wd, "results")
 | 
			
		||||
	f.StringVar(&p.jsonBaseDir, "results-dir", defaultJSONBaseDir, "/path/to/results")
 | 
			
		||||
	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,
 | 
			
		||||
@@ -167,6 +183,18 @@ func (p *ScanCmd) SetFlags(f *flag.FlagSet) {
 | 
			
		||||
		false,
 | 
			
		||||
		"Use external ssh command. Default: Use the Go native implementation")
 | 
			
		||||
 | 
			
		||||
	f.BoolVar(
 | 
			
		||||
		&p.containersOnly,
 | 
			
		||||
		"containers-only",
 | 
			
		||||
		false,
 | 
			
		||||
		"Scan containers only. Default: Scan both of hosts and containers")
 | 
			
		||||
 | 
			
		||||
	f.BoolVar(
 | 
			
		||||
		&p.skipBroken,
 | 
			
		||||
		"skip-broken",
 | 
			
		||||
		false,
 | 
			
		||||
		"[For CentOS] yum update changelog with --skip-broken option")
 | 
			
		||||
 | 
			
		||||
	f.StringVar(
 | 
			
		||||
		&p.httpProxy,
 | 
			
		||||
		"http-proxy",
 | 
			
		||||
@@ -186,6 +214,11 @@ func (p *ScanCmd) SetFlags(f *flag.FlagSet) {
 | 
			
		||||
		false,
 | 
			
		||||
		fmt.Sprintf("Write report to text files (%s/results/current)", wd),
 | 
			
		||||
	)
 | 
			
		||||
	f.BoolVar(&p.reportXML,
 | 
			
		||||
		"report-xml",
 | 
			
		||||
		false,
 | 
			
		||||
		fmt.Sprintf("Write report to XML files (%s/results/current)", wd),
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	f.BoolVar(&p.reportS3,
 | 
			
		||||
		"report-s3",
 | 
			
		||||
@@ -199,7 +232,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")
 | 
			
		||||
@@ -216,7 +249,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",
 | 
			
		||||
	)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -232,10 +265,11 @@ 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
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	c.Conf.Debug = p.debug
 | 
			
		||||
	err = c.Load(p.configPath, keyPass)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		logrus.Errorf("Error loading %s, %s", p.configPath, err)
 | 
			
		||||
@@ -245,7 +279,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)
 | 
			
		||||
	}
 | 
			
		||||
@@ -286,9 +322,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
 | 
			
		||||
@@ -312,6 +348,9 @@ func (p *ScanCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{})
 | 
			
		||||
	if p.reportText {
 | 
			
		||||
		reports = append(reports, report.TextFileWriter{ScannedAt: scannedAt})
 | 
			
		||||
	}
 | 
			
		||||
	if p.reportXML {
 | 
			
		||||
		reports = append(reports, report.XMLWriter{ScannedAt: scannedAt})
 | 
			
		||||
	}
 | 
			
		||||
	if p.reportS3 {
 | 
			
		||||
		c.Conf.AwsRegion = p.awsRegion
 | 
			
		||||
		c.Conf.AwsProfile = p.awsProfile
 | 
			
		||||
@@ -347,7 +386,8 @@ func (p *ScanCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{})
 | 
			
		||||
		reports = append(reports, report.AzureBlobWriter{})
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	c.Conf.JSONBaseDir = p.jsonBaseDir
 | 
			
		||||
	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
 | 
			
		||||
@@ -355,6 +395,8 @@ func (p *ScanCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{})
 | 
			
		||||
	c.Conf.IgnoreUnscoredCves = p.ignoreUnscoredCves
 | 
			
		||||
	c.Conf.SSHExternal = p.sshExternal
 | 
			
		||||
	c.Conf.HTTPProxy = p.httpProxy
 | 
			
		||||
	c.Conf.ContainersOnly = p.containersOnly
 | 
			
		||||
	c.Conf.SkipBroken = p.skipBroken
 | 
			
		||||
 | 
			
		||||
	Log.Info("Validating Config...")
 | 
			
		||||
	if !c.Conf.Validate() {
 | 
			
		||||
@@ -368,7 +410,10 @@ func (p *ScanCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{})
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Log.Info("Detecting Server/Contianer OS... ")
 | 
			
		||||
	scan.InitServers(Log)
 | 
			
		||||
	if err := scan.InitServers(Log); err != nil {
 | 
			
		||||
		Log.Errorf("Failed to init servers: %s", err)
 | 
			
		||||
		return subcommands.ExitFailure
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Log.Info("Checking sudo configuration... ")
 | 
			
		||||
	if err := scan.CheckIfSudoNoPasswd(Log); err != nil {
 | 
			
		||||
 
 | 
			
		||||
@@ -18,6 +18,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
package commands
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"flag"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"os"
 | 
			
		||||
@@ -28,14 +29,13 @@ 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
 | 
			
		||||
type TuiCmd struct {
 | 
			
		||||
	lang        string
 | 
			
		||||
	debugSQL    bool
 | 
			
		||||
	jsonBaseDir string
 | 
			
		||||
	lang       string
 | 
			
		||||
	debugSQL   bool
 | 
			
		||||
	resultsDir string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Name return subcommand name
 | 
			
		||||
@@ -59,15 +59,15 @@ func (p *TuiCmd) SetFlags(f *flag.FlagSet) {
 | 
			
		||||
 | 
			
		||||
	wd, _ := os.Getwd()
 | 
			
		||||
 | 
			
		||||
	defaultJSONBaseDir := filepath.Join(wd, "results")
 | 
			
		||||
	f.StringVar(&p.jsonBaseDir, "results-dir", defaultJSONBaseDir, "/path/to/results")
 | 
			
		||||
	defaultResultsDir := filepath.Join(wd, "results")
 | 
			
		||||
	f.StringVar(&p.resultsDir, "results-dir", defaultResultsDir, "/path/to/results")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Execute execute
 | 
			
		||||
func (p *TuiCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
 | 
			
		||||
	c.Conf.Lang = "en"
 | 
			
		||||
	c.Conf.DebugSQL = p.debugSQL
 | 
			
		||||
	c.Conf.JSONBaseDir = p.jsonBaseDir
 | 
			
		||||
	c.Conf.ResultsDir = p.resultsDir
 | 
			
		||||
 | 
			
		||||
	var jsonDirName string
 | 
			
		||||
	var err error
 | 
			
		||||
 
 | 
			
		||||
@@ -44,10 +44,13 @@ type Config struct {
 | 
			
		||||
	CvssScoreOver      float64
 | 
			
		||||
	IgnoreUnscoredCves bool
 | 
			
		||||
 | 
			
		||||
	SSHExternal bool
 | 
			
		||||
	SSHExternal    bool
 | 
			
		||||
	ContainersOnly bool
 | 
			
		||||
	SkipBroken     bool
 | 
			
		||||
 | 
			
		||||
	HTTPProxy   string `valid:"url"`
 | 
			
		||||
	JSONBaseDir string
 | 
			
		||||
	ResultsDir  string
 | 
			
		||||
	CveDBType   string
 | 
			
		||||
	CveDBPath   string
 | 
			
		||||
	CacheDBPath string
 | 
			
		||||
 | 
			
		||||
@@ -67,17 +70,29 @@ type Config struct {
 | 
			
		||||
func (c Config) Validate() bool {
 | 
			
		||||
	errs := []error{}
 | 
			
		||||
 | 
			
		||||
	if len(c.JSONBaseDir) != 0 {
 | 
			
		||||
		if ok, _ := valid.IsFilePath(c.JSONBaseDir); !ok {
 | 
			
		||||
	if len(c.ResultsDir) != 0 {
 | 
			
		||||
		if ok, _ := valid.IsFilePath(c.ResultsDir); !ok {
 | 
			
		||||
			errs = append(errs, fmt.Errorf(
 | 
			
		||||
				"JSON base directory must be a *Absolute* file path. -results-dir: %s", c.JSONBaseDir))
 | 
			
		||||
				"JSON base directory must be a *Absolute* file path. -results-dir: %s", c.ResultsDir))
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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))
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -187,7 +202,6 @@ type SlackConf struct {
 | 
			
		||||
 | 
			
		||||
// Validate validates configuration
 | 
			
		||||
func (c *SlackConf) Validate() (errs []error) {
 | 
			
		||||
 | 
			
		||||
	if !c.UseThisTime {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
@@ -227,20 +241,35 @@ 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{}
 | 
			
		||||
 | 
			
		||||
	// For CentOS, RHEL, Amazon
 | 
			
		||||
	Enablerepo string
 | 
			
		||||
 | 
			
		||||
	// used internal
 | 
			
		||||
	LogMsgAnsiColor string // DebugLog Color
 | 
			
		||||
	Container       Container
 | 
			
		||||
	Distro          Distro
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetServerName returns ServerName if this serverInfo is about host.
 | 
			
		||||
// If this serverInfo is abount a container, returns containerID@ServerName
 | 
			
		||||
func (s ServerInfo) GetServerName() string {
 | 
			
		||||
	if len(s.Container.ContainerID) == 0 {
 | 
			
		||||
		return s.ServerName
 | 
			
		||||
	}
 | 
			
		||||
	return fmt.Sprintf("%s@%s", s.Container.ContainerID, s.ServerName)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Distro has distribution info
 | 
			
		||||
type Distro struct {
 | 
			
		||||
	Family  string
 | 
			
		||||
 
 | 
			
		||||
@@ -20,10 +20,11 @@ package config
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"os"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"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 +32,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)
 | 
			
		||||
@@ -51,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.")
 | 
			
		||||
		}
 | 
			
		||||
@@ -103,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
 | 
			
		||||
@@ -122,13 +157,28 @@ func (c TOMLLoader) Load(pathToToml, keyPass string) (err error) {
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		s.Enablerepo = v.Enablerepo
 | 
			
		||||
		if len(s.Enablerepo) == 0 {
 | 
			
		||||
			s.Enablerepo = d.Enablerepo
 | 
			
		||||
		}
 | 
			
		||||
		if len(s.Enablerepo) != 0 {
 | 
			
		||||
			for _, repo := range strings.Split(s.Enablerepo, ",") {
 | 
			
		||||
				switch repo {
 | 
			
		||||
				case "base", "updates":
 | 
			
		||||
					// nop
 | 
			
		||||
				default:
 | 
			
		||||
					return fmt.Errorf(
 | 
			
		||||
						"For now, enablerepo have to be base or updates: %s, servername: %s",
 | 
			
		||||
						s.Enablerepo, name)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		s.LogMsgAnsiColor = Colors[i%len(Colors)]
 | 
			
		||||
		i++
 | 
			
		||||
 | 
			
		||||
		servers[name] = s
 | 
			
		||||
	}
 | 
			
		||||
	log.Debug("Config loaded")
 | 
			
		||||
	log.Debugf("%s", pp.Sprintf("%v", servers))
 | 
			
		||||
	Conf.Servers = servers
 | 
			
		||||
	return
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										64
									
								
								contrib/owasp-dependency-check/parser/parser.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								contrib/owasp-dependency-check/parser/parser.go
									
									
									
									
									
										Normal file
									
								
							@@ -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
 | 
			
		||||
}
 | 
			
		||||
@@ -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)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										96
									
								
								glide.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										96
									
								
								glide.lock
									
									
									
										generated
									
									
									
								
							@@ -1,75 +1,81 @@
 | 
			
		||||
hash: 28d14f88e90c0765c1b660ddde796e51e197239d353bb79bfc5d8f8cf9b5f9ee
 | 
			
		||||
updated: 2016-09-08T19:35:45.581570944+09:00
 | 
			
		||||
hash: ca64aef6e9e94c7be91f79b88edb847363c8a5bd48da4ad27784e9342c8db6e2
 | 
			
		||||
updated: 2016-11-01T15:05:15.23083077+09:00
 | 
			
		||||
imports:
 | 
			
		||||
- name: github.com/asaskevich/govalidator
 | 
			
		||||
  version: 593d64559f7600f29581a3ee42177f5dbded27a9
 | 
			
		||||
  version: 7b3beb6df3c42abd3509abfc3bcacc0fbfb7c877
 | 
			
		||||
- name: github.com/aws/aws-sdk-go
 | 
			
		||||
  version: bc572378d109481c50d45d9dba4490d80386e98e
 | 
			
		||||
  version: 9e5bedb97b1cd85e53fd99209f93fd1a8a9f1df7
 | 
			
		||||
  subpackages:
 | 
			
		||||
  - aws
 | 
			
		||||
  - aws/credentials
 | 
			
		||||
  - aws/session
 | 
			
		||||
  - service/s3
 | 
			
		||||
  - aws/awserr
 | 
			
		||||
  - aws/client
 | 
			
		||||
  - aws/corehandlers
 | 
			
		||||
  - aws/credentials/stscreds
 | 
			
		||||
  - aws/defaults
 | 
			
		||||
  - aws/request
 | 
			
		||||
  - private/endpoints
 | 
			
		||||
  - aws/awsutil
 | 
			
		||||
  - aws/client
 | 
			
		||||
  - aws/client/metadata
 | 
			
		||||
  - aws/signer/v4
 | 
			
		||||
  - private/protocol
 | 
			
		||||
  - private/protocol/restxml
 | 
			
		||||
  - private/waiter
 | 
			
		||||
  - service/sts
 | 
			
		||||
  - aws/corehandlers
 | 
			
		||||
  - aws/credentials
 | 
			
		||||
  - aws/credentials/ec2rolecreds
 | 
			
		||||
  - aws/credentials/endpointcreds
 | 
			
		||||
  - aws/credentials/stscreds
 | 
			
		||||
  - aws/defaults
 | 
			
		||||
  - aws/ec2metadata
 | 
			
		||||
  - private/protocol/rest
 | 
			
		||||
  - aws/request
 | 
			
		||||
  - aws/session
 | 
			
		||||
  - aws/signer/v4
 | 
			
		||||
  - private/endpoints
 | 
			
		||||
  - private/protocol
 | 
			
		||||
  - private/protocol/query
 | 
			
		||||
  - private/protocol/xml/xmlutil
 | 
			
		||||
  - private/protocol/query/queryutil
 | 
			
		||||
  - private/protocol/rest
 | 
			
		||||
  - private/protocol/restxml
 | 
			
		||||
  - private/protocol/xml/xmlutil
 | 
			
		||||
  - private/waiter
 | 
			
		||||
  - service/s3
 | 
			
		||||
  - service/sts
 | 
			
		||||
- name: github.com/Azure/azure-sdk-for-go
 | 
			
		||||
  version: 34467930a15f0d2872168deb11435b8ac3d863bb
 | 
			
		||||
  version: 9016164015faa51e549605e7b4b117f7de2aa6f9
 | 
			
		||||
  subpackages:
 | 
			
		||||
  - storage
 | 
			
		||||
- name: github.com/boltdb/bolt
 | 
			
		||||
  version: 074dffcc83e9f421e261526d297cd93f22a34080
 | 
			
		||||
- name: github.com/BurntSushi/toml
 | 
			
		||||
  version: 99064174e013895bbd9b025c31100bd1d9b590ca
 | 
			
		||||
- name: github.com/cenkalti/backoff
 | 
			
		||||
  version: 8edc80b07f38c27352fb186d971c628a6c32552b
 | 
			
		||||
  version: b02f2bbce11d7ea6b97f282ef1771b0fe2f65ef3
 | 
			
		||||
- name: github.com/cheggaaa/pb
 | 
			
		||||
  version: ad4efe000aa550bb54918c06ebbadc0ff17687b9
 | 
			
		||||
- name: github.com/go-ini/ini
 | 
			
		||||
  version: 6e4869b434bd001f6983749881c7ead3545887d8
 | 
			
		||||
- name: github.com/go-sql-driver/mysql
 | 
			
		||||
  version: 2a6c6079c7eff49a7e9d641e109d922f124a3e4c
 | 
			
		||||
- 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: 3ca23474a7c7203e0a0a070fd33508f6efdb9b3d
 | 
			
		||||
  version: f5387c492211eb133053880d23dfae62aa14123d
 | 
			
		||||
- name: github.com/jinzhu/gorm
 | 
			
		||||
  version: 02f6ae3c4ed211472b0492cee02ff3ddfdc1830d
 | 
			
		||||
  version: c1b9cf186e4bcd8e5d566ef43f2ae2dfe22dc34e
 | 
			
		||||
  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: 357a541add9e311f7b67dfbaf92e28c71680a6b7
 | 
			
		||||
- name: github.com/k0kubun/pp
 | 
			
		||||
  version: f5dce6ed0ccf6c350f1679964ff6b61f3d6d2033
 | 
			
		||||
- name: github.com/kotakanbe/go-cve-dictionary
 | 
			
		||||
  version: f9f68fee57dca8e60fb5d9d6b34d3215d854fc06
 | 
			
		||||
  version: 70989b6709c3102924ad8c8483e9bdc99bcb598b
 | 
			
		||||
  subpackages:
 | 
			
		||||
  - config
 | 
			
		||||
  - models
 | 
			
		||||
  - db
 | 
			
		||||
  - log
 | 
			
		||||
  - jvn
 | 
			
		||||
  - log
 | 
			
		||||
  - models
 | 
			
		||||
  - nvd
 | 
			
		||||
  - util
 | 
			
		||||
- name: github.com/kotakanbe/go-pingscanner
 | 
			
		||||
@@ -77,45 +83,41 @@ imports:
 | 
			
		||||
- name: github.com/kotakanbe/logrus-prefixed-formatter
 | 
			
		||||
  version: f4f7d41649cf1e75e736884da8d05324aa76ea25
 | 
			
		||||
- name: github.com/mattn/go-colorable
 | 
			
		||||
  version: ed8eb9e318d7a84ce5915b495b7d35e0cfe7b5a8
 | 
			
		||||
  version: 6c903ff4aa50920ca86087a280590b36b3152b9c
 | 
			
		||||
- 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: e5a3c16c5c1d80b24f633e68aecd6b0702786d3d
 | 
			
		||||
- name: github.com/mgutz/ansi
 | 
			
		||||
  version: c286dcecd19ff979eeb73ea444e479b903f2cfcb
 | 
			
		||||
- name: github.com/moul/http2curl
 | 
			
		||||
  version: b1479103caacaa39319f75e7f57fc545287fca0d
 | 
			
		||||
  version: c984a4ec331f8ef0e5cd782975a97c92bd8ab40c
 | 
			
		||||
- name: github.com/nsf/termbox-go
 | 
			
		||||
  version: e8f6d27f72a2f2bb598eb3579afd5ea364ef67f7
 | 
			
		||||
  version: b6acae516ace002cb8105a89024544a1480655a5
 | 
			
		||||
- name: github.com/parnurzeal/gorequest
 | 
			
		||||
  version: 2aea80ce763523ecc6452e61c3727ae9595a5809
 | 
			
		||||
  version: e37b9d1efacf7c94820b29b75dd7d0c2996b3fb1
 | 
			
		||||
- name: github.com/rifflock/lfshook
 | 
			
		||||
  version: f9d14dda07b109a7aa56f135c31b34062eb14392
 | 
			
		||||
  version: 3f9d976bd7402de39b46357069fb6325a974572e
 | 
			
		||||
- name: github.com/Sirupsen/logrus
 | 
			
		||||
  version: 3ec0642a7fb6488f65b06f9040adc67e3990296a
 | 
			
		||||
- name: golang.org/x/crypto
 | 
			
		||||
  version: 9e590154d2353f3f5e1b24da7275686040dcf491
 | 
			
		||||
  version: 1150b8bd09e53aea1d415621adae9bad665061a1
 | 
			
		||||
  subpackages:
 | 
			
		||||
  - ssh
 | 
			
		||||
  - ssh/agent
 | 
			
		||||
  - ssh/terminal
 | 
			
		||||
  - curve25519
 | 
			
		||||
  - ed25519
 | 
			
		||||
  - ed25519/internal/edwards25519
 | 
			
		||||
  - ssh
 | 
			
		||||
  - ssh/agent
 | 
			
		||||
  - ssh/terminal
 | 
			
		||||
- name: golang.org/x/net
 | 
			
		||||
  version: 9313baa13d9262e49d07b20ed57dceafcd7240cc
 | 
			
		||||
  version: 65dfc08770ce66f74becfdff5f8ab01caef4e946
 | 
			
		||||
  subpackages:
 | 
			
		||||
  - context
 | 
			
		||||
  - publicsuffix
 | 
			
		||||
- name: golang.org/x/sys
 | 
			
		||||
  version: 30de6d19a3bd89a5f38ae4028e23aaa5582648af
 | 
			
		||||
  version: c200b10b5d5e122be351b67af224adc6128af5bf
 | 
			
		||||
  subpackages:
 | 
			
		||||
  - unix
 | 
			
		||||
- name: gopkg.in/alexcesaro/quotedprintable.v3
 | 
			
		||||
  version: 2caba252f4dc53eaf6b553000885530023f54623
 | 
			
		||||
- name: gopkg.in/gomail.v2
 | 
			
		||||
  version: 81ebce5c23dfd25c6c67194b37d3dd3f338c98b1
 | 
			
		||||
devImports: []
 | 
			
		||||
testImports: []
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -168,22 +168,6 @@ FreeBSD: pkg audit<y:LabelModel>
 | 
			
		||||
      </data>
 | 
			
		||||
    </node>
 | 
			
		||||
    <node id="n9">
 | 
			
		||||
      <data key="d6">
 | 
			
		||||
        <y:GenericNode configuration="com.yworks.flowchart.dataBase">
 | 
			
		||||
          <y:Geometry height="64.1719342604298" width="111.96965865992411" x="687.3850119398792" y="807.0697396491782"/>
 | 
			
		||||
          <y:Fill color="#E8EEF7" color2="#B7C9E3" transparent="false"/>
 | 
			
		||||
          <y:BorderStyle color="#000000" type="line" width="1.0"/>
 | 
			
		||||
          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" textColor="#000000" visible="true" width="48.56640625" x="31.701626204962054" y="23.019560880214726">Vuls DB<y:LabelModel>
 | 
			
		||||
              <y:SmartNodeLabelModel distance="4.0"/>
 | 
			
		||||
            </y:LabelModel>
 | 
			
		||||
            <y:ModelParameter>
 | 
			
		||||
              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-8.881784197001252E-16" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
 | 
			
		||||
            </y:ModelParameter>
 | 
			
		||||
          </y:NodeLabel>
 | 
			
		||||
        </y:GenericNode>
 | 
			
		||||
      </data>
 | 
			
		||||
    </node>
 | 
			
		||||
    <node id="n10">
 | 
			
		||||
      <data key="d6">
 | 
			
		||||
        <y:GenericNode configuration="com.yworks.flowchart.dataBase">
 | 
			
		||||
          <y:Geometry height="65.22882427307195" width="136.83944374209864" x="411.5802781289507" y="687.385587863464"/>
 | 
			
		||||
@@ -199,13 +183,13 @@ FreeBSD: pkg audit<y:LabelModel>
 | 
			
		||||
        </y:GenericNode>
 | 
			
		||||
      </data>
 | 
			
		||||
    </node>
 | 
			
		||||
    <node id="n11">
 | 
			
		||||
    <node id="n10">
 | 
			
		||||
      <data key="d6">
 | 
			
		||||
        <y:GenericNode configuration="com.yworks.flowchart.process">
 | 
			
		||||
          <y:Geometry height="56.0" width="268.0" x="609.3698412698412" y="716.4553275126422"/>
 | 
			
		||||
          <y:Fill color="#E8EEF7" color2="#B7C9E3" transparent="false"/>
 | 
			
		||||
          <y:BorderStyle color="#000000" type="line" width="1.0"/>
 | 
			
		||||
          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="32.265625" modelName="custom" textColor="#000000" visible="true" width="126.396484375" x="70.8017578125" y="11.8671875">Insert results into DB
 | 
			
		||||
          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="32.265625" modelName="custom" textColor="#000000" visible="true" width="152.634765625" x="57.6826171875" y="11.8671875">Write results to JSON files
 | 
			
		||||
Reporting<y:LabelModel>
 | 
			
		||||
              <y:SmartNodeLabelModel distance="4.0"/>
 | 
			
		||||
            </y:LabelModel>
 | 
			
		||||
@@ -216,7 +200,7 @@ Reporting<y:LabelModel>
 | 
			
		||||
        </y:GenericNode>
 | 
			
		||||
      </data>
 | 
			
		||||
    </node>
 | 
			
		||||
    <node id="n12">
 | 
			
		||||
    <node id="n11">
 | 
			
		||||
      <data key="d6">
 | 
			
		||||
        <y:GenericNode configuration="com.yworks.flowchart.process">
 | 
			
		||||
          <y:Geometry height="56.0" width="268.0" x="309.6849206349206" y="287.8409153761062"/>
 | 
			
		||||
@@ -233,7 +217,7 @@ CentOS: yum update --changelog<y:LabelModel>
 | 
			
		||||
        </y:GenericNode>
 | 
			
		||||
      </data>
 | 
			
		||||
    </node>
 | 
			
		||||
    <node id="n13">
 | 
			
		||||
    <node id="n12">
 | 
			
		||||
      <data key="d6">
 | 
			
		||||
        <y:GenericNode configuration="com.yworks.flowchart.process">
 | 
			
		||||
          <y:Geometry height="56.0" width="268.0" x="309.6849206349206" y="373.8409153761062"/>
 | 
			
		||||
@@ -364,7 +348,7 @@ FreeBSD<y:LabelModel>
 | 
			
		||||
        </y:PolyLineEdge>
 | 
			
		||||
      </data>
 | 
			
		||||
    </edge>
 | 
			
		||||
    <edge id="e9" source="n7" target="n11">
 | 
			
		||||
    <edge id="e9" source="n7" target="n10">
 | 
			
		||||
      <data key="d10">
 | 
			
		||||
        <y:PolyLineEdge>
 | 
			
		||||
          <y:Path sx="0.0" sy="28.0" tx="0.0" ty="-28.0"/>
 | 
			
		||||
@@ -374,7 +358,7 @@ FreeBSD<y:LabelModel>
 | 
			
		||||
        </y:PolyLineEdge>
 | 
			
		||||
      </data>
 | 
			
		||||
    </edge>
 | 
			
		||||
    <edge id="e10" source="n7" target="n10">
 | 
			
		||||
    <edge id="e10" source="n7" target="n9">
 | 
			
		||||
      <data key="d10">
 | 
			
		||||
        <y:PolyLineEdge>
 | 
			
		||||
          <y:Path sx="-134.01566143419018" sy="6.159084623893818" tx="0.0" ty="-29.333162136535975">
 | 
			
		||||
@@ -386,17 +370,7 @@ FreeBSD<y:LabelModel>
 | 
			
		||||
        </y:PolyLineEdge>
 | 
			
		||||
      </data>
 | 
			
		||||
    </edge>
 | 
			
		||||
    <edge id="e11" source="n11" target="n9">
 | 
			
		||||
      <data key="d10">
 | 
			
		||||
        <y:PolyLineEdge>
 | 
			
		||||
          <y:Path sx="0.0" sy="28.0" tx="0.0" ty="-28.86721713021484"/>
 | 
			
		||||
          <y:LineStyle color="#000000" type="line" width="1.0"/>
 | 
			
		||||
          <y:Arrows source="none" target="none"/>
 | 
			
		||||
          <y:BendStyle smoothed="false"/>
 | 
			
		||||
        </y:PolyLineEdge>
 | 
			
		||||
      </data>
 | 
			
		||||
    </edge>
 | 
			
		||||
    <edge id="e12" source="n1" target="n12">
 | 
			
		||||
    <edge id="e11" source="n1" target="n11">
 | 
			
		||||
      <data key="d10">
 | 
			
		||||
        <y:PolyLineEdge>
 | 
			
		||||
          <y:Path sx="0.0" sy="20.0" tx="0.0" ty="-28.0"/>
 | 
			
		||||
@@ -414,7 +388,7 @@ FreeBSD<y:LabelModel>
 | 
			
		||||
        </y:PolyLineEdge>
 | 
			
		||||
      </data>
 | 
			
		||||
    </edge>
 | 
			
		||||
    <edge id="e13" source="n12" target="n13">
 | 
			
		||||
    <edge id="e12" source="n11" target="n12">
 | 
			
		||||
      <data key="d10">
 | 
			
		||||
        <y:PolyLineEdge>
 | 
			
		||||
          <y:Path sx="0.0" sy="28.0" tx="0.0" ty="-28.0"/>
 | 
			
		||||
@@ -424,7 +398,7 @@ FreeBSD<y:LabelModel>
 | 
			
		||||
        </y:PolyLineEdge>
 | 
			
		||||
      </data>
 | 
			
		||||
    </edge>
 | 
			
		||||
    <edge id="e14" source="n13" target="n7">
 | 
			
		||||
    <edge id="e13" source="n12" target="n7">
 | 
			
		||||
      <data key="d10">
 | 
			
		||||
        <y:PolyLineEdge>
 | 
			
		||||
          <y:Path sx="134.00000000000006" sy="0.0" tx="0.0" ty="-28.0">
 | 
			
		||||
 
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							| 
		 Before Width: | Height: | Size: 85 KiB After Width: | Height: | Size: 81 KiB  | 
							
								
								
									
										11
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								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.7"
 | 
			
		||||
 | 
			
		||||
// 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))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -72,8 +72,8 @@ func (s ScanResults) FilterByCvssOver() (filtered ScanResults) {
 | 
			
		||||
 | 
			
		||||
// ScanResult has the result of scanned CVE information.
 | 
			
		||||
type ScanResult struct {
 | 
			
		||||
	gorm.Model    `json:"-"`
 | 
			
		||||
	ScanHistoryID uint `json:"-"`
 | 
			
		||||
	gorm.Model    `json:"-" xml:"-"`
 | 
			
		||||
	ScanHistoryID uint `json:"-" xml:"-"`
 | 
			
		||||
	ScannedAt     time.Time
 | 
			
		||||
 | 
			
		||||
	ServerName string // TOML Section key
 | 
			
		||||
@@ -89,6 +89,7 @@ type ScanResult struct {
 | 
			
		||||
	//  NWLinks     []NWLink
 | 
			
		||||
	KnownCves   []CveInfo
 | 
			
		||||
	UnknownCves []CveInfo
 | 
			
		||||
	IgnoredCves []CveInfo
 | 
			
		||||
 | 
			
		||||
	Optional [][]interface{} `gorm:"-"`
 | 
			
		||||
}
 | 
			
		||||
@@ -164,10 +165,15 @@ func (r ScanResult) CveSummary() string {
 | 
			
		||||
		high+middle+low+unknown, high, middle, low, unknown)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// AllCves returns Known and Unknown CVEs
 | 
			
		||||
func (r ScanResult) AllCves() []CveInfo {
 | 
			
		||||
	return append(r.KnownCves, r.UnknownCves...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NWLink has network link information.
 | 
			
		||||
type NWLink struct {
 | 
			
		||||
	gorm.Model   `json:"-"`
 | 
			
		||||
	ScanResultID uint `json:"-"`
 | 
			
		||||
	gorm.Model   `json:"-" xml:"-"`
 | 
			
		||||
	ScanResultID uint `json:"-" xml:"-"`
 | 
			
		||||
 | 
			
		||||
	IPAddress string
 | 
			
		||||
	Netmask   string
 | 
			
		||||
@@ -196,8 +202,8 @@ func (c CveInfos) Less(i, j int) bool {
 | 
			
		||||
 | 
			
		||||
// CveInfo has Cve Information.
 | 
			
		||||
type CveInfo struct {
 | 
			
		||||
	gorm.Model   `json:"-"`
 | 
			
		||||
	ScanResultID uint `json:"-"`
 | 
			
		||||
	gorm.Model   `json:"-" xml:"-"`
 | 
			
		||||
	ScanResultID uint `json:"-" xml:"-"`
 | 
			
		||||
 | 
			
		||||
	CveDetail        cve.CveDetail
 | 
			
		||||
	Packages         []PackageInfo
 | 
			
		||||
@@ -207,8 +213,8 @@ type CveInfo struct {
 | 
			
		||||
 | 
			
		||||
// CpeName has CPE name
 | 
			
		||||
type CpeName struct {
 | 
			
		||||
	gorm.Model `json:"-"`
 | 
			
		||||
	CveInfoID  uint `json:"-"`
 | 
			
		||||
	gorm.Model `json:"-" xml:"-"`
 | 
			
		||||
	CveInfoID  uint `json:"-" xml:"-"`
 | 
			
		||||
 | 
			
		||||
	Name string
 | 
			
		||||
}
 | 
			
		||||
@@ -273,15 +279,15 @@ func (ps PackageInfoList) FindByName(name string) (result PackageInfo, found boo
 | 
			
		||||
 | 
			
		||||
// PackageInfo has installed packages.
 | 
			
		||||
type PackageInfo struct {
 | 
			
		||||
	gorm.Model `json:"-"`
 | 
			
		||||
	CveInfoID  uint `json:"-"`
 | 
			
		||||
 | 
			
		||||
	Name    string
 | 
			
		||||
	Version string
 | 
			
		||||
	Release string
 | 
			
		||||
	gorm.Model `json:"-" xml:"-"`
 | 
			
		||||
	CveInfoID  uint `json:"-" xml:"-"`
 | 
			
		||||
 | 
			
		||||
	Name       string
 | 
			
		||||
	Version    string
 | 
			
		||||
	Release    string
 | 
			
		||||
	NewVersion string
 | 
			
		||||
	NewRelease string
 | 
			
		||||
	Repository string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ToStringCurrentVersion returns package name-version-release
 | 
			
		||||
@@ -310,8 +316,8 @@ func (p PackageInfo) ToStringNewVersion() string {
 | 
			
		||||
 | 
			
		||||
// DistroAdvisory has Amazon Linux, RHEL, FreeBSD Security Advisory information.
 | 
			
		||||
type DistroAdvisory struct {
 | 
			
		||||
	gorm.Model `json:"-"`
 | 
			
		||||
	CveInfoID  uint `json:"-"`
 | 
			
		||||
	gorm.Model `json:"-" xml:"-"`
 | 
			
		||||
	CveInfoID  uint `json:"-" xml:"-"`
 | 
			
		||||
 | 
			
		||||
	AdvisoryID string
 | 
			
		||||
	Severity   string
 | 
			
		||||
@@ -321,8 +327,8 @@ type DistroAdvisory struct {
 | 
			
		||||
 | 
			
		||||
// Container has Container information
 | 
			
		||||
type Container struct {
 | 
			
		||||
	gorm.Model   `json:"-"`
 | 
			
		||||
	ScanResultID uint `json:"-"`
 | 
			
		||||
	gorm.Model   `json:"-" xml:"-"`
 | 
			
		||||
	ScanResultID uint `json:"-" xml:"-"`
 | 
			
		||||
 | 
			
		||||
	ContainerID string
 | 
			
		||||
	Name        string
 | 
			
		||||
@@ -330,8 +336,8 @@ type Container struct {
 | 
			
		||||
 | 
			
		||||
// Platform has platform information
 | 
			
		||||
type Platform struct {
 | 
			
		||||
	gorm.Model   `json:"-"`
 | 
			
		||||
	ScanResultID uint `json:"-"`
 | 
			
		||||
	gorm.Model   `json:"-" xml:"-"`
 | 
			
		||||
	ScanResultID uint `json:"-" xml:"-"`
 | 
			
		||||
 | 
			
		||||
	Name       string // aws or azure or gcp or other...
 | 
			
		||||
	InstanceID string
 | 
			
		||||
 
 | 
			
		||||
@@ -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, 0644); 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 {
 | 
			
		||||
@@ -81,7 +73,7 @@ func (w JSONWriter) Write(scanResults []models.ScanResult) (err error) {
 | 
			
		||||
		if jsonBytes, err = json.Marshal(r); err != nil {
 | 
			
		||||
			return fmt.Errorf("Failed to Marshal to JSON: %s", err)
 | 
			
		||||
		}
 | 
			
		||||
		if err := ioutil.WriteFile(jsonPath, jsonBytes, 0644); err != nil {
 | 
			
		||||
		if err := ioutil.WriteFile(jsonPath, jsonBytes, 0600); err != nil {
 | 
			
		||||
			return fmt.Errorf("Failed to write JSON. path: %s, err: %s", jsonPath, err)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@@ -94,13 +86,13 @@ var JSONDirPattern = regexp.MustCompile(`^\d{8}_\d{4}$`)
 | 
			
		||||
// GetValidJSONDirs return valid json directory as array
 | 
			
		||||
func GetValidJSONDirs() (jsonDirs JSONDirs, err error) {
 | 
			
		||||
	var dirInfo []os.FileInfo
 | 
			
		||||
	if dirInfo, err = ioutil.ReadDir(c.Conf.JSONBaseDir); err != nil {
 | 
			
		||||
		err = fmt.Errorf("Failed to read %s: %s", c.Conf.JSONBaseDir, err)
 | 
			
		||||
	if dirInfo, err = ioutil.ReadDir(c.Conf.ResultsDir); err != nil {
 | 
			
		||||
		err = fmt.Errorf("Failed to read %s: %s", c.Conf.ResultsDir, err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	for _, d := range dirInfo {
 | 
			
		||||
		if d.IsDir() && JSONDirPattern.MatchString(d.Name()) {
 | 
			
		||||
			jsonDir := filepath.Join(c.Conf.JSONBaseDir, d.Name())
 | 
			
		||||
			jsonDir := filepath.Join(c.Conf.ResultsDir, d.Name())
 | 
			
		||||
			jsonDirs = append(jsonDirs, jsonDir)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@@ -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
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
@@ -36,7 +36,7 @@ func (w LogrusWriter) Write(scanResults []models.ScanResult) error {
 | 
			
		||||
	if runtime.GOOS == "windows" {
 | 
			
		||||
		path = filepath.Join(os.Getenv("APPDATA"), "vuls", "report.log")
 | 
			
		||||
	}
 | 
			
		||||
	f, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
 | 
			
		||||
	f, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0600)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -18,13 +18,14 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
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
 | 
			
		||||
 | 
			
		||||
		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),
 | 
			
		||||
		)
 | 
			
		||||
 | 
			
		||||
		d.TLSConfig = &tls.Config{
 | 
			
		||||
			InsecureSkipVerify: true,
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if err := d.DialAndSend(m); err != nil {
 | 
			
		||||
			panic(err)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return fmt.Errorf("Failed to send emails: %s", err)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										10
									
								
								report/s3.go
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								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 {
 | 
			
		||||
 
 | 
			
		||||
@@ -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...)
 | 
			
		||||
 
 | 
			
		||||
@@ -49,7 +49,7 @@ func (w TextFileWriter) Write(scanResults []models.ScanResult) (err error) {
 | 
			
		||||
		}
 | 
			
		||||
		all = append(all, text)
 | 
			
		||||
		b := []byte(text)
 | 
			
		||||
		if err := ioutil.WriteFile(textFilePath, b, 0644); err != nil {
 | 
			
		||||
		if err := ioutil.WriteFile(textFilePath, b, 0600); err != nil {
 | 
			
		||||
			return fmt.Errorf("Failed to write text files. path: %s, err: %s", textFilePath, err)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@@ -57,7 +57,7 @@ func (w TextFileWriter) Write(scanResults []models.ScanResult) (err error) {
 | 
			
		||||
	text := strings.Join(all, "\n\n")
 | 
			
		||||
	b := []byte(text)
 | 
			
		||||
	allPath := filepath.Join(path, "all.txt")
 | 
			
		||||
	if err := ioutil.WriteFile(allPath, b, 0644); err != nil {
 | 
			
		||||
	if err := ioutil.WriteFile(allPath, b, 0600); err != nil {
 | 
			
		||||
		return fmt.Errorf("Failed to write text files. path: %s, err: %s", allPath, err)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -73,12 +75,15 @@ func RunTui(jsonDirName string) subcommands.ExitStatus {
 | 
			
		||||
func selectScanHistory(jsonDirName string) (latest models.ScanHistory, err error) {
 | 
			
		||||
	var jsonDir string
 | 
			
		||||
	if 0 < len(jsonDirName) {
 | 
			
		||||
		jsonDir = filepath.Join(config.Conf.JSONBaseDir, jsonDirName)
 | 
			
		||||
		jsonDir = filepath.Join(config.Conf.ResultsDir, jsonDirName)
 | 
			
		||||
	} else {
 | 
			
		||||
		var jsonDirs JSONDirs
 | 
			
		||||
		if jsonDirs, err = GetValidJSONDirs(); err != nil {
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		if len(jsonDirs) == 0 {
 | 
			
		||||
			return latest, fmt.Errorf("No scan results are found in %s", config.Conf.ResultsDir)
 | 
			
		||||
		}
 | 
			
		||||
		jsonDir = jsonDirs[0]
 | 
			
		||||
	}
 | 
			
		||||
	if latest, err = LoadOneScanHistory(jsonDir); err != nil {
 | 
			
		||||
@@ -171,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) {
 | 
			
		||||
@@ -211,7 +222,7 @@ func movable(v *gocui.View, nextY int) (ok bool, yLimit int) {
 | 
			
		||||
		}
 | 
			
		||||
		return true, yLimit
 | 
			
		||||
	case "summary":
 | 
			
		||||
		yLimit = len(currentScanResult.KnownCves) - 1
 | 
			
		||||
		yLimit = len(currentScanResult.AllCves()) - 1
 | 
			
		||||
		if yLimit < nextY {
 | 
			
		||||
			return false, yLimit
 | 
			
		||||
		}
 | 
			
		||||
@@ -368,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
 | 
			
		||||
@@ -376,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
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@@ -386,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
 | 
			
		||||
@@ -394,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
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@@ -459,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
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@@ -481,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
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@@ -492,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
 | 
			
		||||
@@ -527,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
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@@ -541,7 +552,7 @@ func setSummaryLayout(g *gocui.Gui) error {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		lines := summaryLines(currentScanResult)
 | 
			
		||||
		lines := summaryLines()
 | 
			
		||||
		fmt.Fprintf(v, lines)
 | 
			
		||||
 | 
			
		||||
		v.Highlight = true
 | 
			
		||||
@@ -551,21 +562,21 @@ func setSummaryLayout(g *gocui.Gui) error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func summaryLines(data models.ScanResult) string {
 | 
			
		||||
func summaryLines() string {
 | 
			
		||||
	stable := uitable.New()
 | 
			
		||||
	stable.MaxColWidth = 1000
 | 
			
		||||
	stable.Wrap = false
 | 
			
		||||
 | 
			
		||||
	indexFormat := ""
 | 
			
		||||
	if len(data.KnownCves) < 10 {
 | 
			
		||||
	if len(currentScanResult.AllCves()) < 10 {
 | 
			
		||||
		indexFormat = "[%1d]"
 | 
			
		||||
	} else if len(data.KnownCves) < 100 {
 | 
			
		||||
	} else if len(currentScanResult.AllCves()) < 100 {
 | 
			
		||||
		indexFormat = "[%2d]"
 | 
			
		||||
	} else {
 | 
			
		||||
		indexFormat = "[%3d]"
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for i, d := range data.KnownCves {
 | 
			
		||||
	for i, d := range currentScanResult.AllCves() {
 | 
			
		||||
		var cols []string
 | 
			
		||||
		//  packs := []string{}
 | 
			
		||||
		//  for _, pack := range d.Packages {
 | 
			
		||||
@@ -661,11 +672,11 @@ type dataForTmpl struct {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func detailLines() (string, error) {
 | 
			
		||||
	if len(currentScanResult.KnownCves) == 0 {
 | 
			
		||||
	if len(currentScanResult.AllCves()) == 0 {
 | 
			
		||||
		return "No vulnerable packages", nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cveInfo := currentScanResult.KnownCves[currentCveInfo]
 | 
			
		||||
	cveInfo := currentScanResult.AllCves()[currentCveInfo]
 | 
			
		||||
	cveID := cveInfo.CveDetail.CveID
 | 
			
		||||
 | 
			
		||||
	tmpl, err := template.New("detail").Parse(detailTemplate())
 | 
			
		||||
 
 | 
			
		||||
@@ -31,19 +31,21 @@ import (
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func ensureResultDir(scannedAt time.Time) (path string, err error) {
 | 
			
		||||
	if resultDirPath != "" {
 | 
			
		||||
		return resultDirPath, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	const timeLayout = "20060102_1504"
 | 
			
		||||
	timedir := scannedAt.Format(timeLayout)
 | 
			
		||||
	wd, _ := os.Getwd()
 | 
			
		||||
	dir := filepath.Join(wd, "results", timedir)
 | 
			
		||||
	if err := os.MkdirAll(dir, 0755); err != nil {
 | 
			
		||||
	jsonDirName := scannedAt.Format(timeLayout)
 | 
			
		||||
 | 
			
		||||
	resultsDir := config.Conf.ResultsDir
 | 
			
		||||
	if len(resultsDir) == 0 {
 | 
			
		||||
		wd, _ := os.Getwd()
 | 
			
		||||
		resultsDir = filepath.Join(wd, "results")
 | 
			
		||||
	}
 | 
			
		||||
	jsonDir := filepath.Join(resultsDir, jsonDirName)
 | 
			
		||||
 | 
			
		||||
	if err := os.MkdirAll(jsonDir, 0700); err != nil {
 | 
			
		||||
		return "", fmt.Errorf("Failed to create dir: %s", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	symlinkPath := filepath.Join(wd, "results", "current")
 | 
			
		||||
	symlinkPath := filepath.Join(resultsDir, "current")
 | 
			
		||||
	if _, err := os.Lstat(symlinkPath); err == nil {
 | 
			
		||||
		if err := os.Remove(symlinkPath); err != nil {
 | 
			
		||||
			return "", fmt.Errorf(
 | 
			
		||||
@@ -51,11 +53,11 @@ func ensureResultDir(scannedAt time.Time) (path string, err error) {
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := os.Symlink(dir, symlinkPath); err != nil {
 | 
			
		||||
	if err := os.Symlink(jsonDir, symlinkPath); err != nil {
 | 
			
		||||
		return "", fmt.Errorf(
 | 
			
		||||
			"Failed to create symlink: path: %s, err: %s", symlinkPath, err)
 | 
			
		||||
	}
 | 
			
		||||
	return dir, nil
 | 
			
		||||
	return jsonDir, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func toPlainText(scanResult models.ScanResult) (string, error) {
 | 
			
		||||
 
 | 
			
		||||
@@ -39,5 +39,3 @@ const (
 | 
			
		||||
type ResultWriter interface {
 | 
			
		||||
	Write([]models.ScanResult) error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var resultDirPath string
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										54
									
								
								report/xml.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								report/xml.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,54 @@
 | 
			
		||||
package report
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"encoding/xml"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/future-architect/vuls/models"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	vulsOpenTag  = "<vulsreport>"
 | 
			
		||||
	vulsCloseTag = "</vulsreport>"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// XMLWriter writes results to file.
 | 
			
		||||
type XMLWriter struct {
 | 
			
		||||
	ScannedAt time.Time
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (w XMLWriter) Write(scanResults []models.ScanResult) (err error) {
 | 
			
		||||
	var path string
 | 
			
		||||
	if path, err = ensureResultDir(w.ScannedAt); err != nil {
 | 
			
		||||
		return fmt.Errorf("Failed to make direcotory/symlink : %s", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, scanResult := range scanResults {
 | 
			
		||||
		scanResult.ScannedAt = w.ScannedAt
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var xmlBytes []byte
 | 
			
		||||
	for _, r := range scanResults {
 | 
			
		||||
		xmlPath := ""
 | 
			
		||||
		if len(r.Container.ContainerID) == 0 {
 | 
			
		||||
			xmlPath = filepath.Join(path, fmt.Sprintf("%s.xml", r.ServerName))
 | 
			
		||||
		} else {
 | 
			
		||||
			xmlPath = filepath.Join(path,
 | 
			
		||||
				fmt.Sprintf("%s_%s.xml", r.ServerName, r.Container.Name))
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if xmlBytes, err = xml.Marshal(r); err != nil {
 | 
			
		||||
			return fmt.Errorf("Failed to Marshal to XML: %s", err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		allBytes := bytes.Join([][]byte{[]byte(xml.Header + vulsOpenTag), xmlBytes, []byte(vulsCloseTag)}, []byte{})
 | 
			
		||||
		if err := ioutil.WriteFile(xmlPath, allBytes, 0600); err != nil {
 | 
			
		||||
			return fmt.Errorf("Failed to write XML. path: %s, err: %s", xmlPath, err)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										34
									
								
								scan/base.go
									
									
									
									
									
								
							
							
						
						
									
										34
									
								
								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
 | 
			
		||||
@@ -77,6 +78,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":
 | 
			
		||||
@@ -219,13 +224,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
 | 
			
		||||
		}
 | 
			
		||||
@@ -236,10 +259,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)
 | 
			
		||||
@@ -252,6 +276,7 @@ func (l *base) convertToModel() (models.ScanResult, error) {
 | 
			
		||||
 | 
			
		||||
	sort.Sort(scoredCves)
 | 
			
		||||
	sort.Sort(unscoredCves)
 | 
			
		||||
	sort.Sort(ignoredCves)
 | 
			
		||||
 | 
			
		||||
	return models.ScanResult{
 | 
			
		||||
		ServerName:  l.ServerInfo.ServerName,
 | 
			
		||||
@@ -262,6 +287,7 @@ func (l *base) convertToModel() (models.ScanResult, error) {
 | 
			
		||||
		Platform:    l.Platform,
 | 
			
		||||
		KnownCves:   scoredCves,
 | 
			
		||||
		UnknownCves: unscoredCves,
 | 
			
		||||
		IgnoredCves: ignoredCves,
 | 
			
		||||
		Optional:    l.ServerInfo.Optional,
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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.ssh(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
 | 
			
		||||
}
 | 
			
		||||
@@ -247,7 +270,7 @@ func (o *debian) scanUnsecurePackages(packs []models.PackageInfo) ([]CvePacksInf
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	current := cache.Meta{
 | 
			
		||||
		Name:   o.getServerInfo().ServerName,
 | 
			
		||||
		Name:   o.getServerInfo().GetServerName(),
 | 
			
		||||
		Distro: o.getServerInfo().Distro,
 | 
			
		||||
		Packs:  unsecurePacks,
 | 
			
		||||
	}
 | 
			
		||||
@@ -301,7 +324,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.ssh(cmd, sudo)
 | 
			
		||||
	if !r.isSuccess() {
 | 
			
		||||
		return nil, fmt.Errorf("Failed to SSH: %s.", r)
 | 
			
		||||
@@ -323,7 +346,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.ssh(cmd, sudo)
 | 
			
		||||
	if r.isSuccess(0, 1) {
 | 
			
		||||
		return o.parseAptGetUpgrade(r.Stdout)
 | 
			
		||||
@@ -377,7 +400,7 @@ func (o *debian) parseAptGetUpgrade(stdout string) (upgradableNames []string, er
 | 
			
		||||
 | 
			
		||||
func (o *debian) scanPackageCveInfos(unsecurePacks []models.PackageInfo) (cvePacksList CvePacksList, err error) {
 | 
			
		||||
	meta := cache.Meta{
 | 
			
		||||
		Name:   o.getServerInfo().ServerName,
 | 
			
		||||
		Name:   o.getServerInfo().GetServerName(),
 | 
			
		||||
		Distro: o.getServerInfo().Distro,
 | 
			
		||||
		Packs:  unsecurePacks,
 | 
			
		||||
	}
 | 
			
		||||
@@ -490,7 +513,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 ""
 | 
			
		||||
	}
 | 
			
		||||
@@ -518,11 +541,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().ServerName, 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
 | 
			
		||||
 
 | 
			
		||||
@@ -43,6 +43,10 @@ func newBsd(c config.ServerInfo) *bsd {
 | 
			
		||||
//https://github.com/mizzy/specinfra/blob/master/lib/specinfra/helper/detect_os/freebsd.rb
 | 
			
		||||
func detectFreebsd(c config.ServerInfo) (itsMe bool, bsd osTypeInterface) {
 | 
			
		||||
	bsd = newBsd(c)
 | 
			
		||||
 | 
			
		||||
	// Prevent from adding `set -o pipefail` option
 | 
			
		||||
	c.Distro = config.Distro{Family: "FreeBSD"}
 | 
			
		||||
 | 
			
		||||
	if r := sshExec(c, "uname", noSudo); r.isSuccess() {
 | 
			
		||||
		if strings.Contains(r.Stdout, "FreeBSD") == true {
 | 
			
		||||
			if b := sshExec(c, "uname -r", noSudo); b.isSuccess() {
 | 
			
		||||
@@ -62,6 +66,10 @@ func (o *bsd) checkIfSudoNoPasswd() error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *bsd) checkDependencies() error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *bsd) install() error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -112,45 +112,44 @@ 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 = "yum-plugin-changelog"
 | 
			
		||||
		if majorVersion < 6 {
 | 
			
		||||
			packName = "yum-changelog"
 | 
			
		||||
		} else {
 | 
			
		||||
			packName = "yum-plugin-changelog"
 | 
			
		||||
			name = "yum-changelog"
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		cmd := "rpm -q " + packName
 | 
			
		||||
		cmd := "rpm -q " + name
 | 
			
		||||
		if r := o.ssh(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.ssh(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
 | 
			
		||||
}
 | 
			
		||||
@@ -166,11 +165,9 @@ func (o *redhat) checkRequiredPackagesInstalled() error {
 | 
			
		||||
			return fmt.Errorf(msg)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		var packName = ""
 | 
			
		||||
		var packName = "yum-plugin-changelog"
 | 
			
		||||
		if majorVersion < 6 {
 | 
			
		||||
			packName = "yum-changelog"
 | 
			
		||||
		} else {
 | 
			
		||||
			packName = "yum-plugin-changelog"
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		cmd := "rpm -q " + packName
 | 
			
		||||
@@ -251,7 +248,13 @@ 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 %s check-update"
 | 
			
		||||
	if o.getServerInfo().Enablerepo != "" {
 | 
			
		||||
		cmd = fmt.Sprintf(cmd, "--enablerepo="+o.getServerInfo().Enablerepo)
 | 
			
		||||
	} else {
 | 
			
		||||
		cmd = fmt.Sprintf(cmd, "")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	r := o.ssh(util.PrependProxyEnv(cmd), sudo)
 | 
			
		||||
	if !r.isSuccess(0, 100) {
 | 
			
		||||
		//returns an exit code of 100 if there are available updates.
 | 
			
		||||
@@ -399,6 +402,7 @@ func (o *redhat) parseYumCheckUpdateLines(stdout string) (results models.Package
 | 
			
		||||
			}
 | 
			
		||||
			installed.NewVersion = candidate.NewVersion
 | 
			
		||||
			installed.NewRelease = candidate.NewRelease
 | 
			
		||||
			installed.Repository = candidate.Repository
 | 
			
		||||
			results = append(results, installed)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@@ -407,7 +411,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], ".")
 | 
			
		||||
@@ -418,16 +422,19 @@ func (o *redhat) parseYumCheckUpdateLine(line string) (models.PackageInfo, error
 | 
			
		||||
		packName = strings.Join(strings.Split(fields[0], ".")[0:(len(splitted)-1)], ".")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fields = strings.Split(fields[1], "-")
 | 
			
		||||
	if len(fields) != 2 {
 | 
			
		||||
	verfields := strings.Split(fields[1], "-")
 | 
			
		||||
	if len(verfields) != 2 {
 | 
			
		||||
		return models.PackageInfo{}, fmt.Errorf("Unknown format: %s", line)
 | 
			
		||||
	}
 | 
			
		||||
	version := o.regexpReplace(fields[0], `^[0-9]+:`, "")
 | 
			
		||||
	release := fields[1]
 | 
			
		||||
	version := o.regexpReplace(verfields[0], `^[0-9]+:`, "")
 | 
			
		||||
	release := verfields[1]
 | 
			
		||||
	repos := strings.Join(fields[2:len(fields)], " ")
 | 
			
		||||
 | 
			
		||||
	return models.PackageInfo{
 | 
			
		||||
		Name:       packName,
 | 
			
		||||
		NewVersion: version,
 | 
			
		||||
		NewRelease: release,
 | 
			
		||||
		Repository: repos,
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -546,8 +553,15 @@ func (o *redhat) getAllChangelog(packInfoList models.PackageInfoList) (stdout st
 | 
			
		||||
		command += util.ProxyEnv()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	yumopts := ""
 | 
			
		||||
	if o.getServerInfo().Enablerepo != "" {
 | 
			
		||||
		yumopts = " --enablerepo=" + o.getServerInfo().Enablerepo
 | 
			
		||||
	}
 | 
			
		||||
	if config.Conf.SkipBroken {
 | 
			
		||||
		yumopts += " --skip-broken"
 | 
			
		||||
	}
 | 
			
		||||
	// 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 %s --changelog update ", yumopts) + packageNames
 | 
			
		||||
 | 
			
		||||
	r := o.ssh(command, sudo)
 | 
			
		||||
	if !r.isSuccess(0, 1) {
 | 
			
		||||
@@ -589,7 +603,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.ssh(util.PrependProxyEnv(cmd), o.sudo())
 | 
			
		||||
	if !r.isSuccess(0, 100) {
 | 
			
		||||
		//returns an exit code of 100 if there are available updates.
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -658,6 +664,7 @@ bind-utils.x86_64                       30:9.3.6-25.P1.el5_11.8          updates
 | 
			
		||||
					Release:    "4.el6",
 | 
			
		||||
					NewVersion: "2.3.7",
 | 
			
		||||
					NewRelease: "5.el6",
 | 
			
		||||
					Repository: "base",
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					Name:       "bash",
 | 
			
		||||
@@ -665,6 +672,7 @@ bind-utils.x86_64                       30:9.3.6-25.P1.el5_11.8          updates
 | 
			
		||||
					Release:    "33",
 | 
			
		||||
					NewVersion: "4.1.2",
 | 
			
		||||
					NewRelease: "33.el6_7.1",
 | 
			
		||||
					Repository: "updates",
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					Name:       "python-libs",
 | 
			
		||||
@@ -672,6 +680,7 @@ bind-utils.x86_64                       30:9.3.6-25.P1.el5_11.8          updates
 | 
			
		||||
					Release:    "1.1-0",
 | 
			
		||||
					NewVersion: "2.6.6",
 | 
			
		||||
					NewRelease: "64.el6",
 | 
			
		||||
					Repository: "rhui-REGION-rhel-server-releases",
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					Name:       "python-ordereddict",
 | 
			
		||||
@@ -679,6 +688,7 @@ bind-utils.x86_64                       30:9.3.6-25.P1.el5_11.8          updates
 | 
			
		||||
					Release:    "1",
 | 
			
		||||
					NewVersion: "1.1",
 | 
			
		||||
					NewRelease: "3.el6ev",
 | 
			
		||||
					Repository: "installed",
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					Name:       "bind-utils",
 | 
			
		||||
@@ -686,6 +696,15 @@ bind-utils.x86_64                       30:9.3.6-25.P1.el5_11.8          updates
 | 
			
		||||
					Release:    "1",
 | 
			
		||||
					NewVersion: "9.3.6",
 | 
			
		||||
					NewRelease: "25.P1.el5_11.8",
 | 
			
		||||
					Repository: "updates",
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					Name:       "pytalloc",
 | 
			
		||||
					Version:    "2.0.1",
 | 
			
		||||
					Release:    "0",
 | 
			
		||||
					NewVersion: "2.0.7",
 | 
			
		||||
					NewRelease: "2.el6",
 | 
			
		||||
					Repository: "@CentOS 6.5/6.5",
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
@@ -747,6 +766,7 @@ if-not-architecture        100-200                         amzn-main
 | 
			
		||||
					Release:    "0.33.rc1.45.amzn1",
 | 
			
		||||
					NewVersion: "9.8.2",
 | 
			
		||||
					NewRelease: "0.37.rc1.45.amzn1",
 | 
			
		||||
					Repository: "amzn-main",
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					Name:       "java-1.7.0-openjdk",
 | 
			
		||||
@@ -754,6 +774,7 @@ if-not-architecture        100-200                         amzn-main
 | 
			
		||||
					Release:    "2.6.4.0.0.amzn1",
 | 
			
		||||
					NewVersion: "1.7.0.95",
 | 
			
		||||
					NewRelease: "2.6.4.0.65.amzn1",
 | 
			
		||||
					Repository: "amzn-main",
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					Name:       "if-not-architecture",
 | 
			
		||||
@@ -761,6 +782,7 @@ if-not-architecture        100-200                         amzn-main
 | 
			
		||||
					Release:    "20",
 | 
			
		||||
					NewVersion: "100",
 | 
			
		||||
					NewRelease: "200",
 | 
			
		||||
					Repository: "amzn-main",
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
 
 | 
			
		||||
@@ -18,7 +18,10 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
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
 | 
			
		||||
@@ -170,11 +176,20 @@ func PrintSSHableServerNames() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// InitServers detect the kind of OS distribution of target servers
 | 
			
		||||
func InitServers(localLogger *logrus.Entry) {
 | 
			
		||||
func InitServers(localLogger *logrus.Entry) error {
 | 
			
		||||
	Log = localLogger
 | 
			
		||||
	servers = detectServerOSes()
 | 
			
		||||
	if len(servers) == 0 {
 | 
			
		||||
		return fmt.Errorf("No scannable servers")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	containers := detectContainerOSes()
 | 
			
		||||
	servers = append(servers, containers...)
 | 
			
		||||
	if config.Conf.ContainersOnly {
 | 
			
		||||
		servers = containers
 | 
			
		||||
	} else {
 | 
			
		||||
		servers = append(servers, containers...)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func detectServerOSes() (sshAbleOses []osTypeInterface) {
 | 
			
		||||
@@ -247,7 +262,7 @@ func detectContainerOSes() (actives []osTypeInterface) {
 | 
			
		||||
			defer func() {
 | 
			
		||||
				if p := recover(); p != nil {
 | 
			
		||||
					Log.Debugf("Panic: %s on %s",
 | 
			
		||||
						p, s.getServerInfo().ServerName)
 | 
			
		||||
						p, s.getServerInfo().GetServerName())
 | 
			
		||||
				}
 | 
			
		||||
			}()
 | 
			
		||||
			osTypesChan <- detectContainerOSesOnServer(s)
 | 
			
		||||
@@ -369,7 +384,7 @@ func detectContainerOSesOnServer(containerHost osTypeInterface) (oses []osTypeIn
 | 
			
		||||
 | 
			
		||||
// CheckIfSudoNoPasswd checks whether vuls can sudo with nopassword via SSH
 | 
			
		||||
func CheckIfSudoNoPasswd(localLogger *logrus.Entry) error {
 | 
			
		||||
	timeoutSec := 1 * 15
 | 
			
		||||
	timeoutSec := 15
 | 
			
		||||
	errs := parallelSSHExec(func(o osTypeInterface) error {
 | 
			
		||||
		return o.checkIfSudoNoPasswd()
 | 
			
		||||
	}, timeoutSec)
 | 
			
		||||
@@ -416,12 +431,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
 | 
			
		||||
@@ -439,9 +507,12 @@ func Scan() []error {
 | 
			
		||||
	if err := setupCangelogCache(); err != nil {
 | 
			
		||||
		return []error{err}
 | 
			
		||||
	}
 | 
			
		||||
	if cache.DB != nil {
 | 
			
		||||
		defer cache.DB.Close()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	defer func() {
 | 
			
		||||
		if cache.DB != nil {
 | 
			
		||||
			cache.DB.Close()
 | 
			
		||||
		}
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	Log.Info("Scanning vulnerable OS packages...")
 | 
			
		||||
	if errs := scanPackages(); errs != nil {
 | 
			
		||||
 
 | 
			
		||||
@@ -89,7 +89,7 @@ func parallelSSHExec(fn func(osTypeInterface) error, timeoutSec ...int) (errs []
 | 
			
		||||
			defer func() {
 | 
			
		||||
				if p := recover(); p != nil {
 | 
			
		||||
					logrus.Debugf("Panic: %s on %s",
 | 
			
		||||
						p, s.getServerInfo().ServerName)
 | 
			
		||||
						p, s.getServerInfo().GetServerName())
 | 
			
		||||
				}
 | 
			
		||||
			}()
 | 
			
		||||
			if err := fn(s); err != nil {
 | 
			
		||||
@@ -100,7 +100,7 @@ func parallelSSHExec(fn func(osTypeInterface) error, timeoutSec ...int) (errs []
 | 
			
		||||
					err,
 | 
			
		||||
				)
 | 
			
		||||
			} else {
 | 
			
		||||
				resChan <- s.getServerInfo().ServerName
 | 
			
		||||
				resChan <- s.getServerInfo().GetServerName()
 | 
			
		||||
			}
 | 
			
		||||
		}(s)
 | 
			
		||||
	}
 | 
			
		||||
@@ -129,7 +129,7 @@ func parallelSSHExec(fn func(osTypeInterface) error, timeoutSec ...int) (errs []
 | 
			
		||||
	var timedoutSnames []string
 | 
			
		||||
	if isTimedout {
 | 
			
		||||
		for _, s := range servers {
 | 
			
		||||
			name := s.getServerInfo().ServerName
 | 
			
		||||
			name := s.getServerInfo().GetServerName()
 | 
			
		||||
			found := false
 | 
			
		||||
			for _, t := range snames {
 | 
			
		||||
				if name == t {
 | 
			
		||||
 
 | 
			
		||||
@@ -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/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
 | 
			
		||||
	```
 | 
			
		||||
@@ -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
 | 
			
		||||
 | 
			
		||||
1. Locate ssh-keys of targer servers in (vuls/docker/conf/)
 | 
			
		||||
2. Create and ajust config.toml(vuls/docker/conf/config.toml) to your environment
 | 
			
		||||
	
 | 
			
		||||
	```
 | 
			
		||||
	[servers]
 | 
			
		||||
 | 
			
		||||
  	[servers.172-31-4-82]
 | 
			
		||||
  	host        = "172.31.4.82"
 | 
			
		||||
  	user        = "ec2-user"
 | 
			
		||||
  	keyPath     = "conf/id_rsa"
 | 
			
		||||
	```
 | 
			
		||||
 | 
			
		||||
## Fetch Vulnerability database
 | 
			
		||||
 | 
			
		||||
- Fetch Vulnerability database from NVD
 | 
			
		||||
	```
 | 
			
		||||
	$ docker exec -t vuls scripts/fetch_nvd_all.sh
 | 
			
		||||
	```
 | 
			
		||||
 | 
			
		||||
## Scan servers with Vuls-On-Docker
 | 
			
		||||
 | 
			
		||||
- Use the embedded script to scan servers for vulsrepo(or run whatever with docker exec)
 | 
			
		||||
 | 
			
		||||
	```
 | 
			
		||||
	$ 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/
 | 
			
		||||
go-cve-dictionary v0.0.xxx xxxx
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
# Update modules
 | 
			
		||||
- vuls
 | 
			
		||||
 | 
			
		||||
- update vuls, go-cve-dictionary, vulsrepo
 | 
			
		||||
	```
 | 
			
		||||
	$ docker exec -t vuls scripts/update_modules.sh
 | 
			
		||||
	```
 | 
			
		||||
```console
 | 
			
		||||
$ docker run  --rm  vuls/vuls -v
 | 
			
		||||
 | 
			
		||||
# Update Vulnerability database
 | 
			
		||||
vuls v0.0.xxx xxxx
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
- Fetch Vulnerability database from NVD
 | 
			
		||||
	```
 | 
			
		||||
	$ docker exec -t vuls scripts/fetch_nvd_last2y.sh
 | 
			
		||||
	```
 | 
			
		||||
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
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
$ 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
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
- vuls
 | 
			
		||||
 | 
			
		||||
```console
 | 
			
		||||
$ docker run  --rm  vuls/vuls -v
 | 
			
		||||
 | 
			
		||||
vuls v0.1.xxx xxxx
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# How to use this image
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Step2. Configuration
 | 
			
		||||
 | 
			
		||||
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 \
 | 
			
		||||
    -config=./config.toml # path to config.toml in docker
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## 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
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
 
 | 
			
		||||
@@ -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"
 | 
			
		||||
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
 | 
			
		||||
@@ -1,6 +0,0 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
VULS_ROOT=/opt/vuls
 | 
			
		||||
#VULS_CONF=${VULS_ROOT}/conf
 | 
			
		||||
cd $VULS_ROOT
 | 
			
		||||
go-cve-dictionary fetchjvn -last2y
 | 
			
		||||
 | 
			
		||||
@@ -1,5 +0,0 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
VULS_ROOT=/opt/vuls
 | 
			
		||||
#VULS_CONF=${VULS_ROOT}/conf
 | 
			
		||||
cd $VULS_ROOT
 | 
			
		||||
go-cve-dictionary fetchjvn -latest
 | 
			
		||||
@@ -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
 | 
			
		||||
 | 
			
		||||
@@ -1,6 +0,0 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
VULS_ROOT=/opt/vuls
 | 
			
		||||
#VULS_CONF=${VULS_ROOT}/conf
 | 
			
		||||
cd $VULS_ROOT
 | 
			
		||||
go-cve-dictionary fetchnvd -last2y
 | 
			
		||||
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
							
								
								
									
										19
									
								
								setup/docker/go-cve-dictionary/latest/Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								setup/docker/go-cve-dictionary/latest/Dockerfile
									
									
									
									
									
										Normal file
									
								
							@@ -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"]
 | 
			
		||||
							
								
								
									
										89
									
								
								setup/docker/go-cve-dictionary/latest/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								setup/docker/go-cve-dictionary/latest/README.md
									
									
									
									
									
										Normal file
									
								
							@@ -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
 | 
			
		||||
							
								
								
									
										19
									
								
								setup/docker/vuls/latest/Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								setup/docker/vuls/latest/Dockerfile
									
									
									
									
									
										Normal file
									
								
							@@ -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"]
 | 
			
		||||
							
								
								
									
										121
									
								
								setup/docker/vuls/latest/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										121
									
								
								setup/docker/vuls/latest/README.md
									
									
									
									
									
										Normal file
									
								
							@@ -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)
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
# 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
 | 
			
		||||
							
								
								
									
										31
									
								
								setup/docker/vulsrepo/latest/Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								setup/docker/vulsrepo/latest/Dockerfile
									
									
									
									
									
										Normal file
									
								
							@@ -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 "<Directory \"$HTTPD_PREFIX/htdocs/vulsrepo/dist/cgi\">" >> $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 "</Directory>" >> $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"]
 | 
			
		||||
							
								
								
									
										47
									
								
								setup/docker/vulsrepo/latest/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								setup/docker/vulsrepo/latest/README.md
									
									
									
									
									
										Normal file
									
								
							@@ -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
 | 
			
		||||
@@ -18,7 +18,6 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
package util
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"os"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"runtime"
 | 
			
		||||
@@ -53,12 +52,7 @@ func NewCustomLogger(c config.ServerInfo) *logrus.Entry {
 | 
			
		||||
 | 
			
		||||
	whereami := "localhost"
 | 
			
		||||
	if 0 < len(c.ServerName) {
 | 
			
		||||
		if 0 < len(c.Container.ContainerID) {
 | 
			
		||||
			whereami = fmt.Sprintf(
 | 
			
		||||
				"%s_%s", c.ServerName, c.Container.Name)
 | 
			
		||||
		} else {
 | 
			
		||||
			whereami = fmt.Sprintf("%s", c.ServerName)
 | 
			
		||||
		}
 | 
			
		||||
		whereami = c.GetServerName()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if _, err := os.Stat(logDir); err == nil {
 | 
			
		||||
 
 | 
			
		||||
@@ -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 <http://www.gnu.org/licenses/>.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
package version
 | 
			
		||||
 | 
			
		||||
// Name is Vuls
 | 
			
		||||
const Name string = "vuls"
 | 
			
		||||
 | 
			
		||||
// Version of Vuls
 | 
			
		||||
const Version string = "0.1.6"
 | 
			
		||||
		Reference in New Issue
	
	Block a user