Skip to content

Commit

Permalink
Add local scan mode.
Browse files Browse the repository at this point in the history
If the scan target server is localhost, Don't use SSH. #210
  • Loading branch information
kotakanbe committed Jan 12, 2017
1 parent a6912ca commit 18d7b52
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 55 deletions.
14 changes: 7 additions & 7 deletions scan/base.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ type base struct {
errs []error
}

func (l *base) ssh(cmd string, sudo bool) sshResult {
return sshExec(l.ServerInfo, cmd, sudo, l.log)
func (l *base) exec(cmd string, sudo bool) execResult {
return exec(l.ServerInfo, cmd, sudo, l.log)
}

func (l *base) setServerInfo(c config.ServerInfo) {
Expand Down Expand Up @@ -125,7 +125,7 @@ func (l *base) exitedContainers() (containers []config.Container, err error) {

func (l *base) dockerPs(option string) (string, error) {
cmd := fmt.Sprintf("docker ps %s", option)
r := l.ssh(cmd, noSudo)
r := l.exec(cmd, noSudo)
if !r.isSuccess() {
return "", fmt.Errorf("Failed to SSH: %s", r)
}
Expand Down Expand Up @@ -171,9 +171,9 @@ func (l *base) detectPlatform() error {
}

func (l base) detectRunningOnAws() (ok bool, instanceID string, err error) {
if r := l.ssh("type curl", noSudo); r.isSuccess() {
if r := l.exec("type curl", noSudo); r.isSuccess() {
cmd := "curl --max-time 1 --retry 3 --noproxy 169.254.169.254 http://169.254.169.254/latest/meta-data/instance-id"
r := l.ssh(cmd, noSudo)
r := l.exec(cmd, noSudo)
if r.isSuccess() {
id := strings.TrimSpace(r.Stdout)
if !l.isAwsInstanceID(id) {
Expand All @@ -191,9 +191,9 @@ func (l base) detectRunningOnAws() (ok bool, instanceID string, err error) {
}
}

if r := l.ssh("type wget", noSudo); r.isSuccess() {
if r := l.exec("type wget", noSudo); r.isSuccess() {
cmd := "wget --tries=3 --timeout=1 --no-proxy -q -O - http://169.254.169.254/latest/meta-data/instance-id"
r := l.ssh(cmd, noSudo)
r := l.exec(cmd, noSudo)
if r.isSuccess() {
id := strings.TrimSpace(r.Stdout)
if !l.isAwsInstanceID(id) {
Expand Down
30 changes: 15 additions & 15 deletions scan/debian.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@ func newDebian(c config.ServerInfo) *debian {
func detectDebian(c config.ServerInfo) (itsMe bool, deb osTypeInterface, err error) {
deb = newDebian(c)

if r := sshExec(c, "ls /etc/debian_version", noSudo); !r.isSuccess() {
if r := exec(c, "ls /etc/debian_version", noSudo); !r.isSuccess() {
if r.Error != nil {
return false, deb, r.Error
return false, deb, nil
}
if r.ExitStatus == 255 {
return false, deb, fmt.Errorf(
Expand All @@ -60,7 +60,7 @@ func detectDebian(c config.ServerInfo) (itsMe bool, deb osTypeInterface, err err
return false, deb, nil
}

if r := sshExec(c, "lsb_release -ir", noSudo); r.isSuccess() {
if r := exec(c, "lsb_release -ir", noSudo); r.isSuccess() {
// e.g.
// root@fa3ec524be43:/# lsb_release -ir
// Distributor ID: Ubuntu
Expand All @@ -79,7 +79,7 @@ func detectDebian(c config.ServerInfo) (itsMe bool, deb osTypeInterface, err err
return true, deb, nil
}

if r := sshExec(c, "cat /etc/lsb-release", noSudo); r.isSuccess() {
if r := exec(c, "cat /etc/lsb-release", noSudo); r.isSuccess() {
// e.g.
// DISTRIB_ID=Ubuntu
// DISTRIB_RELEASE=14.04
Expand All @@ -100,7 +100,7 @@ func detectDebian(c config.ServerInfo) (itsMe bool, deb osTypeInterface, err err

// Debian
cmd := "cat /etc/debian_version"
if r := sshExec(c, cmd, noSudo); r.isSuccess() {
if r := exec(c, cmd, noSudo); r.isSuccess() {
deb.setDistro("debian", trim(r.Stdout))
return true, deb, nil
}
Expand All @@ -114,7 +114,7 @@ func trim(str string) string {
}

func (o *debian) checkIfSudoNoPasswd() error {
r := o.ssh("apt-get -v", sudo)
r := o.exec("apt-get -v", sudo)
if !r.isSuccess() {
o.log.Errorf("sudo error on %s", r)
return fmt.Errorf("Failed to sudo: %s", r)
Expand All @@ -133,7 +133,7 @@ func (o *debian) checkDependencies() error {
// Because unable to get changelogs via apt-get changelog on Debian.
name := "aptitude"
cmd := name + " -h"
if r := o.ssh(cmd, noSudo); !r.isSuccess() {
if r := o.exec(cmd, noSudo); !r.isSuccess() {
o.lackDependencies = []string{name}
}
return nil
Expand All @@ -151,15 +151,15 @@ func (o *debian) install() error {
// apt-get update
o.log.Infof("apt-get update...")
cmd := util.PrependProxyEnv("apt-get update")
if r := o.ssh(cmd, sudo); !r.isSuccess() {
if r := o.exec(cmd, sudo); !r.isSuccess() {
msg := fmt.Sprintf("Failed to SSH: %s", r)
o.log.Errorf(msg)
return fmt.Errorf(msg)
}

for _, name := range o.lackDependencies {
cmd = util.PrependProxyEnv("apt-get install -y " + name)
if r := o.ssh(cmd, sudo); !r.isSuccess() {
if r := o.exec(cmd, sudo); !r.isSuccess() {
msg := fmt.Sprintf("Failed to SSH: %s", r)
o.log.Errorf(msg)
return fmt.Errorf(msg)
Expand Down Expand Up @@ -188,7 +188,7 @@ func (o *debian) scanPackages() error {
}

func (o *debian) scanInstalledPackages() (packs []models.PackageInfo, err error) {
r := o.ssh("dpkg-query -W", noSudo)
r := o.exec("dpkg-query -W", noSudo)
if !r.isSuccess() {
return packs, fmt.Errorf("Failed to SSH: %s", r)
}
Expand Down Expand Up @@ -232,7 +232,7 @@ func (o *debian) parseScannedPackagesLine(line string) (name, version string, er

func (o *debian) checkRequiredPackagesInstalled() error {
if o.Distro.Family == "debian" {
if r := o.ssh("test -f /usr/bin/aptitude", noSudo); !r.isSuccess() {
if r := o.exec("test -f /usr/bin/aptitude", noSudo); !r.isSuccess() {
msg := fmt.Sprintf("aptitude is not installed: %s", r)
o.log.Errorf(msg)
return fmt.Errorf(msg)
Expand All @@ -244,7 +244,7 @@ func (o *debian) checkRequiredPackagesInstalled() error {
func (o *debian) scanUnsecurePackages(installed []models.PackageInfo) ([]models.VulnInfo, error) {
o.log.Infof("apt-get update...")
cmd := util.PrependProxyEnv("apt-get update")
if r := o.ssh(cmd, sudo); !r.isSuccess() {
if r := o.exec(cmd, sudo); !r.isSuccess() {
return nil, fmt.Errorf("Failed to SSH: %s", r)
}

Expand Down Expand Up @@ -328,7 +328,7 @@ func (o *debian) fillCandidateVersion(before models.PackageInfoList) (filled []m
names = append(names, p.Name)
}
cmd := fmt.Sprintf("LANGUAGE=en_US.UTF-8 apt-cache policy %s", strings.Join(names, " "))
r := o.ssh(cmd, sudo)
r := o.exec(cmd, sudo)
if !r.isSuccess() {
return nil, fmt.Errorf("Failed to SSH: %s", r)
}
Expand All @@ -350,7 +350,7 @@ func (o *debian) fillCandidateVersion(before models.PackageInfoList) (filled []m

func (o *debian) GetUpgradablePackNames() (packNames []string, err error) {
cmd := util.PrependProxyEnv("LANGUAGE=en_US.UTF-8 apt-get upgrade --dry-run")
r := o.ssh(cmd, sudo)
r := o.exec(cmd, sudo)
if r.isSuccess(0, 1) {
return o.parseAptGetUpgrade(r.Stdout)
}
Expand Down Expand Up @@ -529,7 +529,7 @@ func (o *debian) scanPackageCveIDs(pack models.PackageInfo) ([]string, error) {
}
cmd = util.PrependProxyEnv(cmd)

r := o.ssh(cmd, noSudo)
r := o.exec(cmd, noSudo)
if !r.isSuccess() {
o.log.Warnf("Failed to SSH: %s", r)
// Ignore this Error.
Expand Down
10 changes: 5 additions & 5 deletions scan/freebsd.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@ func detectFreebsd(c config.ServerInfo) (itsMe bool, bsd osTypeInterface) {
// Prevent from adding `set -o pipefail` option
c.Distro = config.Distro{Family: "FreeBSD"}

if r := sshExec(c, "uname", noSudo); r.isSuccess() {
if r := exec(c, "uname", noSudo); r.isSuccess() {
if strings.Contains(r.Stdout, "FreeBSD") == true {
if b := sshExec(c, "uname -r", noSudo); b.isSuccess() {
if b := exec(c, "uname -r", noSudo); b.isSuccess() {
rel := strings.TrimSpace(b.Stdout)
bsd.setDistro("FreeBSD", rel)
return true, bsd
Expand Down Expand Up @@ -97,7 +97,7 @@ func (o *bsd) scanPackages() error {

func (o *bsd) scanInstalledPackages() ([]models.PackageInfo, error) {
cmd := util.PrependProxyEnv("pkg version -v")
r := o.ssh(cmd, noSudo)
r := o.exec(cmd, noSudo)
if !r.isSuccess() {
return nil, fmt.Errorf("Failed to SSH: %s", r)
}
Expand All @@ -107,13 +107,13 @@ func (o *bsd) scanInstalledPackages() ([]models.PackageInfo, error) {
func (o *bsd) scanUnsecurePackages() (vulnInfos []models.VulnInfo, err error) {
const vulndbPath = "/tmp/vuln.db"
cmd := "rm -f " + vulndbPath
r := o.ssh(cmd, noSudo)
r := o.exec(cmd, noSudo)
if !r.isSuccess(0) {
return nil, fmt.Errorf("Failed to SSH: %s", r)
}

cmd = util.PrependProxyEnv("pkg audit -F -r -f " + vulndbPath)
r = o.ssh(cmd, noSudo)
r = o.exec(cmd, noSudo)
if !r.isSuccess(0, 1) {
return nil, fmt.Errorf("Failed to SSH: %s", r)
}
Expand Down
32 changes: 16 additions & 16 deletions scan/redhat.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,18 +48,18 @@ func newRedhat(c config.ServerInfo) *redhat {
func detectRedhat(c config.ServerInfo) (itsMe bool, red osTypeInterface) {
red = newRedhat(c)

if r := sshExec(c, "ls /etc/fedora-release", noSudo); r.isSuccess() {
if r := exec(c, "ls /etc/fedora-release", noSudo); r.isSuccess() {
red.setDistro("fedora", "unknown")
Log.Warn("Fedora not tested yet: %s", r)
return true, red
}

if r := sshExec(c, "ls /etc/redhat-release", noSudo); r.isSuccess() {
if r := exec(c, "ls /etc/redhat-release", noSudo); r.isSuccess() {
// https://www.rackaid.com/blog/how-to-determine-centos-or-red-hat-version/
// e.g.
// $ cat /etc/redhat-release
// CentOS release 6.5 (Final)
if r := sshExec(c, "cat /etc/redhat-release", noSudo); r.isSuccess() {
if r := exec(c, "cat /etc/redhat-release", noSudo); r.isSuccess() {
re := regexp.MustCompile(`(.*) release (\d[\d.]*)`)
result := re.FindStringSubmatch(strings.TrimSpace(r.Stdout))
if len(result) != 3 {
Expand All @@ -79,10 +79,10 @@ func detectRedhat(c config.ServerInfo) (itsMe bool, red osTypeInterface) {
return true, red
}

if r := sshExec(c, "ls /etc/system-release", noSudo); r.isSuccess() {
if r := exec(c, "ls /etc/system-release", noSudo); r.isSuccess() {
family := "amazon"
release := "unknown"
if r := sshExec(c, "cat /etc/system-release", noSudo); r.isSuccess() {
if r := exec(c, "cat /etc/system-release", noSudo); r.isSuccess() {
fields := strings.Fields(r.Stdout)
if len(fields) == 5 {
release = fields[4]
Expand All @@ -97,7 +97,7 @@ func detectRedhat(c config.ServerInfo) (itsMe bool, red osTypeInterface) {
}

func (o *redhat) checkIfSudoNoPasswd() error {
r := o.ssh("yum --version", o.sudo())
r := o.exec("yum --version", o.sudo())
if !r.isSuccess() {
o.log.Errorf("sudo error on %s", r)
return fmt.Errorf("Failed to sudo: %s", r)
Expand Down Expand Up @@ -128,7 +128,7 @@ func (o *redhat) checkDependencies() error {
}

cmd := "rpm -q " + name
if r := o.ssh(cmd, noSudo); r.isSuccess() {
if r := o.exec(cmd, noSudo); r.isSuccess() {
return nil
}
o.lackDependencies = []string{name}
Expand All @@ -142,7 +142,7 @@ func (o *redhat) checkDependencies() error {
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() {
if r := o.exec(cmd, sudo); !r.isSuccess() {
return fmt.Errorf("Failed to SSH: %s", r)
}
o.log.Infof("Installed: %s", name)
Expand All @@ -165,7 +165,7 @@ func (o *redhat) checkRequiredPackagesInstalled() error {
}

cmd := "rpm -q " + packName
if r := o.ssh(cmd, noSudo); !r.isSuccess() {
if r := o.exec(cmd, noSudo); !r.isSuccess() {
msg := fmt.Sprintf("%s is not installed", packName)
o.log.Errorf(msg)
return fmt.Errorf(msg)
Expand Down Expand Up @@ -194,7 +194,7 @@ func (o *redhat) scanPackages() error {

func (o *redhat) scanInstalledPackages() (installedPackages models.PackageInfoList, err error) {
cmd := "rpm -qa --queryformat '%{NAME}\t%{VERSION}\t%{RELEASE}\n'"
r := o.ssh(cmd, noSudo)
r := o.exec(cmd, noSudo)
if r.isSuccess() {
// e.g.
// openssl 1.0.1e 30.el6.11
Expand Down Expand Up @@ -249,7 +249,7 @@ func (o *redhat) scanUnsecurePackagesUsingYumCheckUpdate() (models.VulnInfos, er
cmd = fmt.Sprintf(cmd, "")
}

r := o.ssh(util.PrependProxyEnv(cmd), sudo)
r := o.exec(util.PrependProxyEnv(cmd), sudo)
if !r.isSuccess(0, 100) {
//returns an exit code of 100 if there are available updates.
return nil, fmt.Errorf("Failed to SSH: %s", r)
Expand Down Expand Up @@ -543,7 +543,7 @@ func (o *redhat) getAllChangelog(packInfoList models.PackageInfoList) (stdout st
// yum update --changelog doesn't have --color option.
command += fmt.Sprintf(" LANGUAGE=en_US.UTF-8 yum %s --changelog update ", yumopts) + packageNames

r := o.ssh(command, sudo)
r := o.exec(command, sudo)
if !r.isSuccess(0, 1) {
return "", fmt.Errorf(
"Failed to get changelog. status: %d, stdout: %s, stderr: %s",
Expand All @@ -568,7 +568,7 @@ func (o *redhat) scanUnsecurePackagesUsingYumPluginSecurity() (models.VulnInfos,
}

cmd := "yum --color=never repolist"
r := o.ssh(util.PrependProxyEnv(cmd), o.sudo())
r := o.exec(util.PrependProxyEnv(cmd), o.sudo())
if !r.isSuccess() {
return nil, fmt.Errorf("Failed to SSH: %s", r)
}
Expand All @@ -589,7 +589,7 @@ func (o *redhat) scanUnsecurePackagesUsingYumPluginSecurity() (models.VulnInfos,
cmd = "yum --color=never updateinfo list available --security"
}
}
r = o.ssh(util.PrependProxyEnv(cmd), o.sudo())
r = o.exec(util.PrependProxyEnv(cmd), o.sudo())
if !r.isSuccess() {
return nil, fmt.Errorf("Failed to SSH: %s", r)
}
Expand All @@ -598,7 +598,7 @@ func (o *redhat) scanUnsecurePackagesUsingYumPluginSecurity() (models.VulnInfos,
// get package name, version, rel to be upgrade.
// cmd = "yum check-update --security"
cmd = "LANGUAGE=en_US.UTF-8 yum --color=never check-update"
r = o.ssh(util.PrependProxyEnv(cmd), o.sudo())
r = o.exec(util.PrependProxyEnv(cmd), o.sudo())
if !r.isSuccess(0, 100) {
//returns an exit code of 100 if there are available updates.
return nil, fmt.Errorf("Failed to SSH: %s", r)
Expand Down Expand Up @@ -638,7 +638,7 @@ func (o *redhat) scanUnsecurePackagesUsingYumPluginSecurity() (models.VulnInfos,
cmd = "yum --color=never updateinfo --security update"
}
}
r = o.ssh(util.PrependProxyEnv(cmd), o.sudo())
r = o.exec(util.PrependProxyEnv(cmd), o.sudo())
if !r.isSuccess() {
return nil, fmt.Errorf("Failed to SSH: %s", r)
}
Expand Down
3 changes: 3 additions & 0 deletions scan/serverapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,9 @@ func detectOS(c config.ServerInfo) (osType osTypeInterface) {
Log.Debugf("FreeBSD. Host: %s:%s", c.Host, c.Port)
return
}

//TODO darwin https://github.com/mizzy/specinfra/blob/master/lib/specinfra/helper/detect_os/darwin.rb

osType.setServerInfo(c)
osType.setErrs([]error{fmt.Errorf("Unknown OS Type")})
return
Expand Down
Loading

0 comments on commit 18d7b52

Please sign in to comment.