diff --git a/README.md b/README.md index fd83eac9..adcb8d2a 100644 --- a/README.md +++ b/README.md @@ -239,7 +239,7 @@ $ vuls tui ![Vuls-Architecture](img/vuls-architecture.png) -## go-cve-dictinary +## [go-cve-dictinary](https://github.com/kotakanbe/go-cve-dictionary) - Fetch vulnerability information from NVD, JVN(Japanese), then insert into SQLite. ## Vuls @@ -314,9 +314,7 @@ subjectPrefix = "[vuls]" [default] #port = "22" #user = "username" -#password = "password" #keyPath = "/home/username/.ssh/id_rsa" -#keyPassword = "password" [servers] @@ -324,9 +322,7 @@ subjectPrefix = "[vuls]" host = "172.31.4.82" #port = "22" #user = "root" -#password = "password" #keyPath = "/home/username/.ssh/id_rsa" -#keyPassword = "password" #cpeNames = [ # "cpe:/a:rubyonrails:ruby_on_rails:4.2.1", #] @@ -394,9 +390,7 @@ You can customize your configuration using this template. [default] #port = "22" #user = "username" - #password = "password" #keyPath = "/home/username/.ssh/id_rsa" - #keyPassword = "password" ``` Items of the default section will be used if not specified. @@ -408,9 +402,7 @@ You can customize your configuration using this template. host = "172.31.4.82" #port = "22" #user = "root" - #password = "password" #keyPath = "/home/username/.ssh/id_rsa" - #keyPassword = "password" #cpeNames = [ # "cpe:/a:rubyonrails:ruby_on_rails:4.2.1", #] @@ -439,9 +431,15 @@ Prepare subcommand installs required packages on each server. ``` $ vuls prepare -help -prepare: - prepare [-config=/path/to/config.toml] [-debug] +prepare + [-config=/path/to/config.toml] [-debug] + [-ask-sudo-password] + [-ask-key-password] + -ask-key-password + Ask ssh privatekey password before scanning + -ask-sudo-password + Ask sudo password of target servers before scanning -config string /path/to/toml (default "$PWD/config.toml") -debug @@ -455,6 +453,7 @@ prepare: # Usage: Scan ``` + $ vuls scan -help scan: scan @@ -466,8 +465,14 @@ scan: [-report-slack] [-report-mail] [-http-proxy=http://192.168.0.1:8080] + [-ask-sudo-password] + [-ask-key-password] [-debug] [-debug-sql] + -ask-key-password + Ask ssh privatekey password before scanning + -ask-sudo-password + Ask sudo password of target servers before scanning -config string /path/to/toml (default "$PWD/config.toml") -cve-dictionary-url string @@ -495,6 +500,21 @@ scan: ``` +## ask-key-password option + +| SSH key password | -ask-key-password || +|:-----------------|:-------------------|| +| empty password | - || +| with password | required | or use ssh-agent | + +## ask-sudo-password option + +| sudo password on target servers | -ask-sudo-password || +|:-----------------|:-------------------|| +| NOPASSWORD | - | defined as NOPASSWORD in /etc/sudoers on target servers | +| with password | required || + + ## example Run go-cve-dictionary as server mode before scanning. @@ -504,9 +524,10 @@ $ go-cve-dictionary server ### Scan all servers defined in config file ``` -$ vuls scan --report-slack --report-mail --cvss-over=7 +$ vuls scan --report-slack --report-mail --cvss-over=7 -ask-sudo-password -ask-key-password ``` With this sample command, it will .. +- Ask sudo password and ssh key passsword 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 @@ -517,7 +538,9 @@ With this sample command, it will .. $ vuls scan server1 server2 ``` With this sample command, it will .. -- Scan only 2 servers. (server1, server2) +- Use SSH Key-Based authentication with empty password (without -ask-key-password option) +- Sudo with no password (without -ask-sudo-password option) +- Scan only 2 servers (server1, server2) - Print scan result to terminal ---- @@ -530,6 +553,9 @@ It is possible to detect vulnerabilities something you compiled by yourself, the - [NVD: Search Common Platform Enumerations (CPE)](https://web.nvd.nist.gov/view/cpe/search) **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. + - Configuration To detect the vulnerbility of Ruby on Rails v4.2.1, cpeNames needs to be set in the servers section. ``` @@ -590,6 +616,11 @@ Use Systemd, Upstart or supervisord, daemontools... - How to Enable Automatic-Update of Vunerability Data. Use job scheduler like Cron (with -last2y option). +- How to Enable Automatic-Scan. +Use job scheduler like Cron. +Set NOPASSWORD option in /etc/sudoers on target servers. +Use SSH Key-Based Authentication with empty password or ssh-agent. + - How to cross compile ```bash $ cd /path/to/your/local-git-reporsitory/vuls diff --git a/commands/prepare.go b/commands/prepare.go index 9cfc3458..d3daf9bb 100644 --- a/commands/prepare.go +++ b/commands/prepare.go @@ -59,9 +59,10 @@ func (*PrepareCmd) Synopsis() string { func (*PrepareCmd) Usage() string { return `prepare: prepare - [-config=/path/to/config.toml] [-debug] + [-config=/path/to/config.toml] [-ask-sudo-password] [-ask-key-password] + [-debug] ` } @@ -78,7 +79,7 @@ func (p *PrepareCmd) SetFlags(f *flag.FlagSet) { &p.askKeyPassword, "ask-key-password", false, - "Ask ssh privatekey password of target servers before scanning", + "Ask ssh privatekey password before scanning", ) f.BoolVar( diff --git a/commands/scan.go b/commands/scan.go index e186ff0b..272a29f5 100644 --- a/commands/scan.go +++ b/commands/scan.go @@ -116,6 +116,13 @@ func (p *ScanCmd) SetFlags(f *flag.FlagSet) { f.BoolVar(&p.reportSlack, "report-slack", false, "Slack report") f.BoolVar(&p.reportMail, "report-mail", false, "Email report") + f.BoolVar( + &p.askKeyPassword, + "ask-key-password", + false, + "Ask ssh privatekey password before scanning", + ) + f.BoolVar( &p.askSudoPassword, "ask-sudo-password", @@ -123,13 +130,6 @@ func (p *ScanCmd) SetFlags(f *flag.FlagSet) { "Ask sudo password of target servers before scanning", ) - f.BoolVar( - &p.askKeyPassword, - "ask-key-password", - false, - "Ask ssh privatekey password of target servers before scanning", - ) - f.BoolVar( &p.useYumPluginSecurity, "use-yum-plugin-security", diff --git a/config/tomlloader.go b/config/tomlloader.go index 3f9578a5..6b031f63 100644 --- a/config/tomlloader.go +++ b/config/tomlloader.go @@ -45,15 +45,32 @@ func (c TOMLLoader) Load(pathToToml, keyPass, sudoPass string) (err error) { Conf.Default = d servers := make(map[string]ServerInfo) + if keyPass != "" { + d.KeyPassword = keyPass + } + + if sudoPass != "" { + d.Password = sudoPass + } + i := 0 for name, v := range conf.Servers { + + if 0 < len(v.KeyPassword) || 0 < len(v.Password) { + log.Warn("[Depricated] password and keypassword in config file are unsecure. Remove them immediately for a security reason. They will be removed in a future release.") + } + s := ServerInfo{ServerName: name} s.User = v.User if s.User == "" { s.User = d.User } - s.Password = sudoPass + // s.Password = sudoPass + s.Password = v.Password + if s.Password == "" { + s.Password = d.Password + } s.Host = v.Host @@ -73,7 +90,11 @@ func (c TOMLLoader) Load(pathToToml, keyPass, sudoPass string) (err error) { } } - s.KeyPassword = keyPass + // s.KeyPassword = keyPass + s.KeyPassword = v.KeyPassword + if s.KeyPassword == "" { + s.KeyPassword = d.KeyPassword + } s.CpeNames = v.CpeNames if len(s.CpeNames) == 0 { diff --git a/scan/redhat.go b/scan/redhat.go index 5111a083..dfc46e75 100644 --- a/scan/redhat.go +++ b/scan/redhat.go @@ -129,6 +129,7 @@ func (o *redhat) installYumPluginSecurity() error { return nil } + o.log.Info("Installing yum-plugin-security...") cmd := util.PrependProxyEnv("yum install -y yum-plugin-security") if r := o.ssh(cmd, sudo); !r.isSuccess() { return fmt.Errorf( @@ -139,7 +140,6 @@ func (o *redhat) installYumPluginSecurity() error { } func (o *redhat) installYumChangelog() error { - o.log.Info("Installing yum-plugin-security...") if o.Family == "centos" { var majorVersion int @@ -164,6 +164,7 @@ func (o *redhat) installYumChangelog() error { return nil } + o.log.Infof("Installing %s...", packName) cmd = util.PrependProxyEnv("yum install -y " + packName) if r := o.ssh(cmd, sudo); !r.isSuccess() { return fmt.Errorf( @@ -459,6 +460,9 @@ func (o *redhat) parseYumCheckUpdateLine(line string) (models.PackageInfo, error func (o *redhat) getChangelog(packageNames string) (stdout string, err error) { command := "" + if o.ServerInfo.User == "root" { + command = "yes no | " + } if 0 < len(config.Conf.HTTPProxy) { command += util.ProxyEnv() } diff --git a/scan/sshutil.go b/scan/sshutil.go index 00c2a97f..df39c49a 100644 --- a/scan/sshutil.go +++ b/scan/sshutil.go @@ -226,7 +226,8 @@ func sshConnect(c conf.ServerInfo) (client *ssh.Client, err error) { var auths = []ssh.AuthMethod{} if auths, err = addKeyAuth(auths, c.KeyPath, c.KeyPassword); err != nil { - logrus.Fatalf("Failed to add keyAuth. err: %s", err) + logrus.Fatalf("Failed to add keyAuth. %s@%s:%s err: %s", + c.User, c.Host, c.Port, err) } if c.Password != "" { @@ -238,12 +239,10 @@ func sshConnect(c conf.ServerInfo) (client *ssh.Client, err error) { User: c.User, Auth: auths, } - // log.Debugf("config: %s", pp.Sprintf("%v", config)) notifyFunc := func(e error, t time.Duration) { logrus.Warnf("Failed to ssh %s@%s:%s err: %s, Retrying in %s...", c.User, c.Host, c.Port, e, t) - logrus.Debugf("sshConInfo: %s", pp.Sprintf("%v", c)) } err = backoff.RetryNotify(func() error { if client, err = ssh.Dial("tcp", c.Host+":"+c.Port, config); err != nil {