Add IP address to scan results (#602)
This commit is contained in:
		
				
					committed by
					
						
						Kota Kanbe
					
				
			
			
				
	
			
			
			
						parent
						
							562ff7807d
						
					
				
				
					commit
					7a5793c562
				
			@@ -474,6 +474,10 @@ type ServerInfo struct {
 | 
			
		||||
	LogMsgAnsiColor string // DebugLog Color
 | 
			
		||||
	Container       Container
 | 
			
		||||
	Distro          Distro
 | 
			
		||||
 | 
			
		||||
	// IP addresses
 | 
			
		||||
	IPv4Addrs []string
 | 
			
		||||
	IPv6Addrs []string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetServerName returns ServerName if this serverInfo is about host.
 | 
			
		||||
 
 | 
			
		||||
@@ -40,6 +40,8 @@ type ScanResult struct {
 | 
			
		||||
	Release     string
 | 
			
		||||
	Container   Container
 | 
			
		||||
	Platform    Platform
 | 
			
		||||
	IPv4Addrs   []string // only global unicast address (https://golang.org/pkg/net/#IP.IsGlobalUnicast)
 | 
			
		||||
	IPv6Addrs   []string // only global unicast address (https://golang.org/pkg/net/#IP.IsGlobalUnicast)
 | 
			
		||||
 | 
			
		||||
	// Scanned Vulns by SSH scan + CPE + OVAL
 | 
			
		||||
	ScannedCves VulnInfos
 | 
			
		||||
 
 | 
			
		||||
@@ -82,6 +82,23 @@ func (o *alpine) apkUpdate() error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *alpine) preCure() error {
 | 
			
		||||
	if err := o.detectIPAddr(); err != nil {
 | 
			
		||||
		o.log.Debugf("Failed to detect IP addresses: %s", err)
 | 
			
		||||
	}
 | 
			
		||||
	// Ignore this error as it just failed to detect the IP addresses
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *alpine) postScan() error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *alpine) detectIPAddr() (err error) {
 | 
			
		||||
	o.ServerInfo.IPv4Addrs, o.ServerInfo.IPv6Addrs, err = o.ip()
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *alpine) scanPackages() error {
 | 
			
		||||
	if err := o.apkUpdate(); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										41
									
								
								scan/base.go
									
									
									
									
									
								
							
							
						
						
									
										41
									
								
								scan/base.go
									
									
									
									
									
								
							@@ -19,6 +19,7 @@ package scan
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"net"
 | 
			
		||||
	"regexp"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
@@ -256,6 +257,44 @@ func (l *base) parseLxcPs(stdout string) (containers []config.Container, err err
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ip executes ip command and returns IP addresses
 | 
			
		||||
func (l *base) ip() ([]string, []string, error) {
 | 
			
		||||
	// e.g.
 | 
			
		||||
	// 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000\    link/ether 52:54:00:2a:86:4c brd ff:ff:ff:ff:ff:ff
 | 
			
		||||
	// 2: eth0    inet 10.0.2.15/24 brd 10.0.2.255 scope global eth0
 | 
			
		||||
	// 2: eth0    inet6 fe80::5054:ff:fe2a:864c/64 scope link \       valid_lft forever preferred_lft forever
 | 
			
		||||
	r := l.exec("/sbin/ip -o addr", noSudo)
 | 
			
		||||
	if !r.isSuccess() {
 | 
			
		||||
		return nil, nil, fmt.Errorf("Failed to detect IP address: %v", r)
 | 
			
		||||
	}
 | 
			
		||||
	ipv4Addrs, ipv6Addrs := l.parseIP(r.Stdout)
 | 
			
		||||
	return ipv4Addrs, ipv6Addrs, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// parseIP parses the results of ip command
 | 
			
		||||
func (l *base) parseIP(stdout string) (ipv4Addrs []string, ipv6Addrs []string) {
 | 
			
		||||
	lines := strings.Split(stdout, "\n")
 | 
			
		||||
	for _, line := range lines {
 | 
			
		||||
		fields := strings.Fields(line)
 | 
			
		||||
		if len(fields) < 4 {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		ip, _, err := net.ParseCIDR(fields[3])
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		if !ip.IsGlobalUnicast() {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		if ipv4 := ip.To4(); ipv4 != nil {
 | 
			
		||||
			ipv4Addrs = append(ipv4Addrs, ipv4.String())
 | 
			
		||||
		} else {
 | 
			
		||||
			ipv6Addrs = append(ipv6Addrs, ip.String())
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (l *base) detectPlatform() {
 | 
			
		||||
	ok, instanceID, err := l.detectRunningOnAws()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
@@ -352,6 +391,8 @@ func (l *base) convertToModel() models.ScanResult {
 | 
			
		||||
		Release:       l.Distro.Release,
 | 
			
		||||
		Container:     container,
 | 
			
		||||
		Platform:      l.Platform,
 | 
			
		||||
		IPv4Addrs:     l.ServerInfo.IPv4Addrs,
 | 
			
		||||
		IPv6Addrs:     l.ServerInfo.IPv6Addrs,
 | 
			
		||||
		ScannedCves:   l.VulnInfos,
 | 
			
		||||
		RunningKernel: l.Kernel,
 | 
			
		||||
		Packages:      l.Packages,
 | 
			
		||||
 
 | 
			
		||||
@@ -97,6 +97,36 @@ func TestParseLxdPs(t *testing.T) {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestParseIp(t *testing.T) {
 | 
			
		||||
 | 
			
		||||
	var test = struct {
 | 
			
		||||
		in        string
 | 
			
		||||
		expected4 []string
 | 
			
		||||
		expected6 []string
 | 
			
		||||
	}{
 | 
			
		||||
		in: `1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN \    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
 | 
			
		||||
1: lo    inet 127.0.0.1/8 scope host lo
 | 
			
		||||
1: lo    inet6 ::1/128 scope host \       valid_lft forever preferred_lft forever
 | 
			
		||||
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000\    link/ether 52:54:00:2a:86:4c brd ff:ff:ff:ff:ff:ff
 | 
			
		||||
2: eth0    inet 10.0.2.15/24 brd 10.0.2.255 scope global eth0
 | 
			
		||||
2: eth0    inet6 fe80::5054:ff:fe2a:864c/64 scope link \       valid_lft forever preferred_lft forever
 | 
			
		||||
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000\    link/ether 08:00:27:36:76:60 brd ff:ff:ff:ff:ff:ff
 | 
			
		||||
3: eth1    inet 192.168.33.11/24 brd 192.168.33.255 scope global eth1
 | 
			
		||||
3: eth1    inet6 2001:db8::68/64 scope link \       valid_lft forever preferred_lft forever `,
 | 
			
		||||
		expected4: []string{"10.0.2.15", "192.168.33.11"},
 | 
			
		||||
		expected6: []string{"2001:db8::68"},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	r := newRedhat(config.ServerInfo{})
 | 
			
		||||
	actual4, actual6 := r.parseIP(test.in)
 | 
			
		||||
	if !reflect.DeepEqual(test.expected4, actual4) {
 | 
			
		||||
		t.Errorf("expected %v, actual %v", test.expected4, actual4)
 | 
			
		||||
	}
 | 
			
		||||
	if !reflect.DeepEqual(test.expected6, actual6) {
 | 
			
		||||
		t.Errorf("expected %v, actual %v", test.expected6, actual6)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestIsAwsInstanceID(t *testing.T) {
 | 
			
		||||
	var tests = []struct {
 | 
			
		||||
		in       string
 | 
			
		||||
 
 | 
			
		||||
@@ -186,6 +186,23 @@ func (o *debian) checkDependencies() error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *debian) preCure() error {
 | 
			
		||||
	if err := o.detectIPAddr(); err != nil {
 | 
			
		||||
		o.log.Debugf("Failed to detect IP addresses: %s", err)
 | 
			
		||||
	}
 | 
			
		||||
	// Ignore this error as it just failed to detect the IP addresses
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *debian) postScan() error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *debian) detectIPAddr() (err error) {
 | 
			
		||||
	o.ServerInfo.IPv4Addrs, o.ServerInfo.IPv6Addrs, err = o.ip()
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *debian) scanPackages() error {
 | 
			
		||||
	// collect the running kernel information
 | 
			
		||||
	release, version, err := o.runningKernel()
 | 
			
		||||
 
 | 
			
		||||
@@ -19,6 +19,7 @@ package scan
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"net"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"github.com/future-architect/vuls/config"
 | 
			
		||||
@@ -77,6 +78,51 @@ func (o *bsd) checkDependencies() error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *bsd) preCure() error {
 | 
			
		||||
	if err := o.detectIPAddr(); err != nil{
 | 
			
		||||
		o.log.Debugf("Failed to detect IP addresses: %s", err)
 | 
			
		||||
	}
 | 
			
		||||
	// Ignore this error as it just failed to detect the IP addresses
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *bsd) postScan() error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *bsd) detectIPAddr() (err error) {
 | 
			
		||||
	r := o.exec("/sbin/ifconfig", noSudo)
 | 
			
		||||
	if !r.isSuccess() {
 | 
			
		||||
		return fmt.Errorf("Failed to detect IP address: %v", r)
 | 
			
		||||
	}
 | 
			
		||||
	o.ServerInfo.IPv4Addrs, o.ServerInfo.IPv6Addrs = o.parseIfconfig(r.Stdout)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (l *base) parseIfconfig(stdout string) (ipv4Addrs []string, ipv6Addrs []string) {
 | 
			
		||||
	lines := strings.Split(stdout, "\n")
 | 
			
		||||
	for _, line := range lines {
 | 
			
		||||
		line = strings.TrimSpace(line)
 | 
			
		||||
		fields := strings.Fields(line)
 | 
			
		||||
		if len(fields) < 4 || !strings.HasPrefix(fields[0], "inet") {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		ip := net.ParseIP(fields[1])
 | 
			
		||||
		if ip == nil {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		if !ip.IsGlobalUnicast() {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		if ipv4 := ip.To4(); ipv4 != nil {
 | 
			
		||||
			ipv4Addrs = append(ipv4Addrs, ipv4.String())
 | 
			
		||||
		} else {
 | 
			
		||||
			ipv6Addrs = append(ipv6Addrs, ip.String())
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *bsd) scanPackages() error {
 | 
			
		||||
	// collect the running kernel information
 | 
			
		||||
	release, version, err := o.runningKernel()
 | 
			
		||||
 
 | 
			
		||||
@@ -9,6 +9,45 @@ import (
 | 
			
		||||
	"github.com/k0kubun/pp"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestParseIfconfig(t *testing.T) {
 | 
			
		||||
	var tests = []struct {
 | 
			
		||||
		in        string
 | 
			
		||||
		expected4 []string
 | 
			
		||||
		expected6 []string
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			in: `em0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
 | 
			
		||||
			options=9b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM>
 | 
			
		||||
			ether 08:00:27:81:82:fa
 | 
			
		||||
			hwaddr 08:00:27:81:82:fa
 | 
			
		||||
			inet 10.0.2.15 netmask 0xffffff00 broadcast 10.0.2.255
 | 
			
		||||
			inet6 2001:db8::68 netmask 0xffffff00 broadcast 10.0.2.255
 | 
			
		||||
			nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>
 | 
			
		||||
			media: Ethernet autoselect (1000baseT <full-duplex>)
 | 
			
		||||
			status: active
 | 
			
		||||
	lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> metric 0 mtu 16384
 | 
			
		||||
			options=600003<RXCSUM,TXCSUM,RXCSUM_IPV6,TXCSUM_IPV6>
 | 
			
		||||
			inet6 ::1 prefixlen 128
 | 
			
		||||
			inet6 fe80::1%lo0 prefixlen 64 scopeid 0x2
 | 
			
		||||
			inet 127.0.0.1 netmask 0xff000000
 | 
			
		||||
			nd6 options=21<PERFORMNUD,AUTO_LINKLOCAL>`,
 | 
			
		||||
			expected4: []string{"10.0.2.15"},
 | 
			
		||||
			expected6: []string{"2001:db8::68"},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	d := newBsd(config.ServerInfo{})
 | 
			
		||||
	for _, tt := range tests {
 | 
			
		||||
		actual4, actual6 := d.parseIfconfig(tt.in)
 | 
			
		||||
		if !reflect.DeepEqual(tt.expected4, actual4) {
 | 
			
		||||
			t.Errorf("expected %s, actual %s", tt.expected4, actual4)
 | 
			
		||||
		}
 | 
			
		||||
		if !reflect.DeepEqual(tt.expected6, actual6) {
 | 
			
		||||
			t.Errorf("expected %s, actual %s", tt.expected6, actual6)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestParsePkgVersion(t *testing.T) {
 | 
			
		||||
	var tests = []struct {
 | 
			
		||||
		in       string
 | 
			
		||||
 
 | 
			
		||||
@@ -56,6 +56,14 @@ func (o *pseudo) checkDependencies() error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *pseudo) preCure() error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *pseudo) postScan() error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *pseudo) scanPackages() error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -246,6 +246,23 @@ func (o *redhat) checkDependencies() error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *redhat) preCure() error {
 | 
			
		||||
	if err := o.detectIPAddr(); err != nil {
 | 
			
		||||
		o.log.Debugf("Failed to detect IP addresses: %s", err)
 | 
			
		||||
	}
 | 
			
		||||
	// Ignore this error as it just failed to detect the IP addresses
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *redhat) postScan() error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *redhat) detectIPAddr() (err error) {
 | 
			
		||||
	o.ServerInfo.IPv4Addrs, o.ServerInfo.IPv6Addrs, err = o.ip()
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *redhat) scanPackages() error {
 | 
			
		||||
	installed, err := o.scanInstalledPackages()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
 
 | 
			
		||||
@@ -44,6 +44,8 @@ type osTypeInterface interface {
 | 
			
		||||
	checkDependencies() error
 | 
			
		||||
	checkIfSudoNoPasswd() error
 | 
			
		||||
 | 
			
		||||
	preCure() error
 | 
			
		||||
	postScan() error
 | 
			
		||||
	scanPackages() error
 | 
			
		||||
	convertToModel() models.ScanResult
 | 
			
		||||
 | 
			
		||||
@@ -454,8 +456,14 @@ func setupChangelogCache() error {
 | 
			
		||||
 | 
			
		||||
func scanVulns(jsonDir string, scannedAt time.Time, timeoutSec int) error {
 | 
			
		||||
	var results models.ScanResults
 | 
			
		||||
	parallelExec(func(o osTypeInterface) error {
 | 
			
		||||
		return o.scanPackages()
 | 
			
		||||
	parallelExec(func(o osTypeInterface) (err error) {
 | 
			
		||||
		if err = o.preCure(); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		if err = o.scanPackages(); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		return o.postScan()
 | 
			
		||||
	}, timeoutSec)
 | 
			
		||||
 | 
			
		||||
	for _, s := range append(servers, errServers...) {
 | 
			
		||||
 
 | 
			
		||||
@@ -30,6 +30,14 @@ func (o *unknown) checkDependencies() error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *unknown) preCure() error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *unknown) postScan() error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *unknown) scanPackages() error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user