Add IP address to scan results (#602)

This commit is contained in:
Teppei Fukuda
2018-02-19 12:50:00 +09:00
committed by Kota Kanbe
parent 562ff7807d
commit 7a5793c562
12 changed files with 239 additions and 2 deletions

View File

@@ -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.

View File

@@ -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

View File

@@ -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

View File

@@ -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,

View File

@@ -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

View File

@@ -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()

View File

@@ -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()

View File

@@ -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

View File

@@ -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
}

View File

@@ -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 {

View File

@@ -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...) {

View File

@@ -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
}