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 16, 2017
1 parent 910385b commit 39c3cea
Show file tree
Hide file tree
Showing 11 changed files with 128 additions and 160 deletions.
1 change: 1 addition & 0 deletions README.ja.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ NVDから脆弱性データベースを取得する。
環境によって異なるが、AWS上では10分程度かかる。

```bash
$ cd $HOME
$ for i in {2002..2016}; do go-cve-dictionary fetchnvd -years $i; done
... snip ...
$ ls -alh cve.sqlite3
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ Fetch vulnerability data from NVD.
It takes about 10 minutes (on AWS).

```bash
$ cd $HOME
$ for i in {2002..2016}; do go-cve-dictionary fetchnvd -years $i; done
... snip ...
$ ls -alh cve.sqlite3
Expand Down
60 changes: 28 additions & 32 deletions models/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,47 +162,43 @@ func (r ScanResult) ReportKeyName() (name string) {

// ServerInfo returns server name one line
func (r ScanResult) ServerInfo() string {
hostinfo := ""
if len(r.Container.ContainerID) == 0 {
hostinfo = fmt.Sprintf(
"%s (%s%s)",
r.ServerName,
r.Family,
r.Release,
)
} else {
hostinfo = fmt.Sprintf(
"%s / %s (%s%s) on %s",
r.Container.Name,
r.Container.ContainerID,
r.Family,
r.Release,
r.ServerName,
return fmt.Sprintf("%s (%s%s)",
r.ServerName, r.Family, r.Release,
)
}
return hostinfo
return fmt.Sprintf(
"%s / %s (%s%s) on %s",
r.Container.Name,
r.Container.ContainerID,
r.Family,
r.Release,
r.ServerName,
)
}

// ServerInfoTui returns server infromation for TUI sidebar
func (r ScanResult) ServerInfoTui() string {
hostinfo := ""
if len(r.Container.ContainerID) == 0 {
hostinfo = fmt.Sprintf(
"%s (%s%s)",
r.ServerName,
r.Family,
r.Release,
)
} else {
hostinfo = fmt.Sprintf(
"|-- %s (%s%s)",
r.Container.Name,
r.Family,
r.Release,
// r.Container.ContainerID,
)
return fmt.Sprintf("%s (%s%s)",
r.ServerName, r.Family, r.Release)
}
return fmt.Sprintf(
"|-- %s (%s%s)",
r.Container.Name,
r.Family,
r.Release,
// r.Container.ContainerID,
)
}

// FormatServerName returns server and contianer name
func (r ScanResult) FormatServerName() string {
if len(r.Container.ContainerID) == 0 {
return r.ServerName
}
return hostinfo
return fmt.Sprintf("%s@%s",
r.Container.Name, r.ServerName)
}

// CveSummary summarize the number of CVEs group by CVSSv2 Severity
Expand Down
4 changes: 2 additions & 2 deletions report/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func toScanSummary(rs ...models.ScanResult) string {
table.Wrap = true
for _, r := range rs {
cols := []interface{}{
r.ServerName,
r.FormatServerName(),
fmt.Sprintf("%s%s", r.Family, r.Release),
fmt.Sprintf("%d CVEs", len(r.ScannedCves)),
r.Packages.ToUpdatablePacksSummary(),
Expand All @@ -51,7 +51,7 @@ func toOneLineSummary(rs ...models.ScanResult) string {
table.Wrap = true
for _, r := range rs {
cols := []interface{}{
r.ServerName,
r.FormatServerName(),
r.CveSummary(),
r.Packages.ToUpdatablePacksSummary(),
}
Expand Down
18 changes: 9 additions & 9 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 @@ -143,7 +143,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 All @@ -152,7 +152,7 @@ func (l *base) dockerPs(option string) (string, error) {

func (l *base) lxdPs(option string) (string, error) {
cmd := fmt.Sprintf("lxc list %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 @@ -180,7 +180,7 @@ func (l *base) parseDockerPs(stdout string) (containers []config.Container, err
func (l *base) parseLxdPs(stdout string) (containers []config.Container, err error) {
lines := strings.Split(stdout, "\n")
for i, line := range lines[3:] {
if i % 2 == 1 {
if i%2 == 1 {
continue
}
fields := strings.Fields(strings.Replace(line, "|", " ", -1))
Expand Down Expand Up @@ -219,9 +219,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 @@ -239,9 +239,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
Loading

0 comments on commit 39c3cea

Please sign in to comment.