Change models structure

This commit is contained in:
Kota Kanbe
2017-05-04 13:57:22 +09:00
committed by kota kanbe
parent b545b5d0a3
commit c103b79ec2
16 changed files with 1022 additions and 1005 deletions

28
Gopkg.lock generated
View File

@@ -4,13 +4,13 @@ memo = "bd95ed8c2b0aa32327ae55d88bff888b8198d238f7a71eee0f8663494664a0ac"
branch = "master"
name = "github.com/Azure/azure-storage-go"
packages = ["."]
revision = "12ccaadb081cdd217702067d28da9a7ff4305239"
revision = "4fe73b0b4f68bf8a7cad2920ef563fe4c40ac5c0"
[[projects]]
name = "github.com/Azure/go-autorest"
packages = ["autorest","autorest/azure","autorest/date"]
revision = "a2fdd780c9a50455cecd249b00bdc3eb73a78e31"
version = "v7.3.1"
packages = ["autorest","autorest/adal","autorest/azure","autorest/date"]
revision = "58f6f26e200fa5dfb40c9cd1c83f3e2c860d779d"
version = "v8.0.0"
[[projects]]
name = "github.com/BurntSushi/toml"
@@ -22,7 +22,7 @@ memo = "bd95ed8c2b0aa32327ae55d88bff888b8198d238f7a71eee0f8663494664a0ac"
branch = "master"
name = "github.com/Sirupsen/logrus"
packages = ["."]
revision = "10f801ebc38b33738c9d17d50860f484a0988ff5"
revision = "508f304878257fb578be3e863e3990ed9ec3aa2e"
[[projects]]
name = "github.com/asaskevich/govalidator"
@@ -141,7 +141,7 @@ memo = "bd95ed8c2b0aa32327ae55d88bff888b8198d238f7a71eee0f8663494664a0ac"
branch = "master"
name = "github.com/kotakanbe/goval-dictionary"
packages = ["config","db","log","models"]
revision = "5470d7565a9de51593f53327ce14c97d466b05ab"
revision = "545199055508ae62a6d3bd34ef83034fbfc04d7f"
[[projects]]
branch = "master"
@@ -221,6 +221,12 @@ memo = "bd95ed8c2b0aa32327ae55d88bff888b8198d238f7a71eee0f8663494664a0ac"
revision = "2adb3e0c4ddd8778c4adde609d2dfd4fbe6096ea"
version = "1.6"
[[projects]]
name = "github.com/satori/uuid"
packages = ["."]
revision = "879c5887cd475cd7864858769793b2ceb0d44feb"
version = "v1.1.0"
[[projects]]
branch = "master"
name = "github.com/valyala/bytebufferpool"
@@ -237,28 +243,28 @@ memo = "bd95ed8c2b0aa32327ae55d88bff888b8198d238f7a71eee0f8663494664a0ac"
branch = "master"
name = "github.com/ymomoi/goval-parser"
packages = ["oval"]
revision = "4ddf6fc4f1a1af026f7cae41f76979c7ff2b2e2f"
revision = "003ac9af5fffac6c97ab1def025d2cb73e88469a"
[[projects]]
branch = "master"
name = "golang.org/x/crypto"
packages = ["curve25519","ed25519","ed25519/internal/edwards25519","ssh","ssh/agent","ssh/terminal"]
revision = "c7af5bf2638a1164f2eb5467c39c6cffbd13a02e"
revision = "04eae0b62feaaf659a0ce2c4e8dc70b6ae2fff67"
[[projects]]
branch = "master"
name = "golang.org/x/net"
packages = ["context","idna","publicsuffix"]
revision = "da118f7b8e5954f39d0d2130ab35d4bf0e3cb344"
revision = "feeb485667d1fdabe727840fe00adc22431bc86e"
[[projects]]
branch = "master"
name = "golang.org/x/sys"
packages = ["unix"]
revision = "9f30dcbe5be197894515a338a9bda9253567ea8f"
revision = "9ccfe848b9db8435a24c424abbc07a921adf1df5"
[[projects]]
branch = "master"
name = "golang.org/x/text"
packages = ["internal/gen","internal/triegen","internal/ucd","secure/bidirule","transform","unicode/bidi","unicode/cldr","unicode/norm","unicode/rangetable"]
revision = "a9a820217f98f7c8a207ec1e45a874e1fe12c478"
revision = "470f45bf29f4147d6fbd7dfd0a02a848e49f5bf4"

View File

@@ -422,7 +422,6 @@ func (p *ReportCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}
util.Log.Errorf("Failed to fill OVAL information: %s", err)
return subcommands.ExitFailure
}
pp.Println(filled)
filled, err = fillCveInfoFromCveDB(*filled)
if err != nil {
@@ -463,6 +462,13 @@ func (p *ReportCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}
var res models.ScanResults
for _, r := range results {
//TODO remove
for _, vuln := range r.ScannedCves {
if _, ok := vuln.CveContents.Get(models.CveContentType(r.Family)); !ok {
fmt.Println("not in oval")
pp.Println(vuln)
}
}
res = append(res, r.FilterByCvssOver())
}

View File

@@ -231,8 +231,9 @@ func diff(current, previous models.ScanResults) (diff models.ScanResults, err er
if found {
currentResult.ScannedCves = getNewCves(previousResult, currentResult)
currentResult.KnownCves = []models.CveInfo{}
currentResult.UnknownCves = []models.CveInfo{}
//TODO
// currentResult.KnownCves = []models.CveInfo{}
// currentResult.UnknownCves = []models.CveInfo{}
currentResult.Packages = models.PackageInfoList{}
for _, s := range currentResult.ScannedCves {
@@ -270,27 +271,28 @@ func isCveInfoUpdated(current, previous models.ScanResult, CveID string) bool {
Jvn time.Time
}
//TODO
previousModifies := lastModified{}
for _, c := range previous.KnownCves {
for _, c := range previous.ScannedCves {
if CveID == c.CveID {
//TODO
if nvd, found := c.Get(models.NVD); found {
if nvd, found := c.CveContents.Get(models.NVD); found {
previousModifies.Nvd = nvd.LastModified
}
if jvn, found := c.Get(models.JVN); found {
if jvn, found := c.CveContents.Get(models.JVN); found {
previousModifies.Jvn = jvn.LastModified
}
}
}
currentModifies := lastModified{}
for _, c := range current.KnownCves {
if CveID == c.VulnInfo.CveID {
for _, c := range current.ScannedCves {
if CveID == c.CveID {
//TODO
if nvd, found := c.Get(models.NVD); found {
if nvd, found := c.CveContents.Get(models.NVD); found {
previousModifies.Nvd = nvd.LastModified
}
if jvn, found := c.Get(models.JVN); found {
if jvn, found := c.CveContents.Get(models.JVN); found {
previousModifies.Jvn = jvn.LastModified
}
}
@@ -352,7 +354,14 @@ func scanVulnByCpeNames(cpeNames []string, scannedVulns []models.VulnInfo) ([]mo
}
func needToRefreshCve(r models.ScanResult) bool {
return r.Lang != c.Conf.Lang || len(r.KnownCves) == 0 &&
len(r.UnknownCves) == 0 &&
len(r.IgnoredCves) == 0
if r.Lang != c.Conf.Lang {
return true
}
for _, cve := range r.ScannedCves {
if 0 < len(cve.CveContents) {
return false
}
}
return true
}

View File

@@ -69,6 +69,7 @@ type response struct {
CveDetail cve.CveDetail
}
//TODO rename to FetchCveDictionary
func (api cvedictClient) FetchCveDetails(cveIDs []string) (cveDetails cve.CveDetails, err error) {
switch config.Conf.CveDBType {
case "sqlite3", "mysql", "postgres":

View File

@@ -60,25 +60,19 @@ type ScanResult struct {
Container Container
Platform Platform
// Scanned Vulns via SSH + CPE Vulns
ScannedCves []VulnInfo
KnownCves CveInfos
UnknownCves CveInfos
IgnoredCves CveInfos
// Scanned Vulns by SSH scan + CPE + OVAL
ScannedCves VulnInfos
Packages PackageInfoList
Errors []string
Optional [][]interface{}
}
// FillCveDetail fetches NVD, JVN from CVE Database, and then set to fields.
//TODO rename to FillCveDictionary
func (r ScanResult) FillCveDetail() (*ScanResult, error) {
set := map[string]VulnInfo{}
var cveIDs []string
for _, v := range r.ScannedCves {
set[v.CveID] = v
cveIDs = append(cveIDs, v.CveID)
}
@@ -86,64 +80,24 @@ func (r ScanResult) FillCveDetail() (*ScanResult, error) {
if err != nil {
return nil, err
}
r.IgnoredCves = CveInfos{}
for _, d := range ds {
nvd := *r.convertNvdToModel(d.CveID, d.Nvd)
jvn := *r.convertJvnToModel(d.CveID, d.Jvn)
cinfo := CveInfo{
CveContents: []CveContent{nvd, jvn},
VulnInfo: set[d.CveID],
}
cinfo.NilSliceToEmpty()
// ignored
ignore := false
for _, icve := range config.Conf.Servers[r.ServerName].IgnoreCves {
if icve == d.CveID {
r.IgnoredCves.Insert(cinfo)
ignore = true
for i, sc := range r.ScannedCves {
if sc.CveID == d.CveID {
for _, con := range []CveContent{nvd, jvn} {
if !con.Empty() {
r.ScannedCves[i].CveContents.Upsert(con)
}
}
break
}
}
if ignore {
continue
}
// Update known if KnownCves already have cinfo
if c, ok := r.KnownCves.Get(cinfo.CveID); ok {
for _, con := range []CveContent{nvd, jvn} {
if !c.Update(con) {
c.Insert(con)
}
}
r.KnownCves.Update(c)
continue
}
// Update unknown if UnknownCves already have cinfo
if c, ok := r.UnknownCves.Get(cinfo.CveID); ok {
for _, con := range []CveContent{nvd, jvn} {
if !c.Update(con) {
c.Insert(con)
}
}
r.UnknownCves.Update(c)
continue
}
// unknown
if d.CvssScore(config.Conf.Lang) <= 0 {
r.UnknownCves.Insert(cinfo)
continue
}
// known
r.KnownCves.Insert(cinfo)
}
sort.Sort(r.KnownCves)
sort.Sort(r.UnknownCves)
sort.Sort(r.IgnoredCves)
//TODO sort
// sort.Sort(r.KnownCves)
// sort.Sort(r.UnknownCves)
// sort.Sort(r.IgnoredCves)
return &r, nil
}
@@ -236,19 +190,21 @@ func (r ScanResult) convertJvnToModel(cveID string, jvn cvedict.Jvn) *CveContent
// FilterByCvssOver is filter function.
func (r ScanResult) FilterByCvssOver() ScanResult {
cveInfos := []CveInfo{}
// TODO: Set correct default value
if config.Conf.CvssScoreOver == 0 {
config.Conf.CvssScoreOver = -1.1
}
for _, cveInfo := range r.KnownCves {
if config.Conf.CvssScoreOver <= cveInfo.CvssV2Score() {
cveInfos = append(cveInfos, cveInfo)
// TODO: Filter by ignore cves???
filtered := VulnInfos{}
for _, sc := range r.ScannedCves {
if config.Conf.CvssScoreOver <= sc.CveContents.CvssV2Score() {
filtered = append(filtered, sc)
}
}
r.KnownCves = cveInfos
return r
copiedScanResult := r
copiedScanResult.ScannedCves = filtered
return copiedScanResult
}
// ReportFileName returns the filename on localhost without extention
@@ -311,9 +267,8 @@ func (r ScanResult) FormatServerName() string {
// CveSummary summarize the number of CVEs group by CVSSv2 Severity
func (r ScanResult) CveSummary() string {
var high, medium, low, unknown int
cves := append(r.KnownCves, r.UnknownCves...)
for _, cveInfo := range cves {
score := cveInfo.CvssV2Score()
for _, vInfo := range r.ScannedCves {
score := vInfo.CveContents.CvssV2Score()
switch {
case 7.0 <= score:
high++
@@ -334,18 +289,14 @@ func (r ScanResult) CveSummary() string {
high+medium+low+unknown, high, medium, low, unknown)
}
// AllCves returns Known and Unknown CVEs
func (r ScanResult) AllCves() []CveInfo {
return append(r.KnownCves, r.UnknownCves...)
}
// NWLink has network link information.
type NWLink struct {
IPAddress string
Netmask string
DevName string
LinkState string
}
//TODO remove
// type NWLink struct {
// IPAddress string
// Netmask string
// DevName string
// LinkState string
// }
// Confidence is a ranking how confident the CVE-ID was deteted correctly
// Score: 0 - 100
@@ -405,6 +356,89 @@ var ChangelogLenientMatch = Confidence{50, ChangelogLenientMatchStr}
// VulnInfos is VulnInfo list, getter/setter, sortable methods.
type VulnInfos []VulnInfo
// FindByCveID find by CVEID
// TODO remove
// func (v *VulnInfos) FindByCveID(cveID string) (VulnInfo, bool) {
// for _, p := range s {
// if cveID == p.CveID {
// return p, true
// }
// }
// return VulnInfo{CveID: cveID}, false
// }
// Get VulnInfo by cveID
func (v *VulnInfos) Get(cveID string) (VulnInfo, bool) {
for _, vv := range *v {
if vv.CveID == cveID {
return vv, true
}
}
return VulnInfo{}, false
}
// Delete by cveID
func (v *VulnInfos) Delete(cveID string) {
vInfos := *v
for i, vv := range vInfos {
if vv.CveID == cveID {
*v = append(vInfos[:i], vInfos[i+1:]...)
break
}
}
}
// Insert VulnInfo
func (v *VulnInfos) Insert(vinfo VulnInfo) {
*v = append(*v, vinfo)
}
// Update VulnInfo
func (v *VulnInfos) Update(vInfo VulnInfo) (ok bool) {
for i, vv := range *v {
if vv.CveID == vInfo.CveID {
(*v)[i] = vInfo
return true
}
}
return false
}
// Upsert cveInfo
func (v *VulnInfos) Upsert(vInfo VulnInfo) {
ok := v.Update(vInfo)
if !ok {
v.Insert(vInfo)
}
}
// immutable
// func (v *VulnInfos) set(cveID string, v VulnInfo) VulnInfos {
// for i, p := range s {
// if cveID == p.CveID {
// s[i] = v
// return s
// }
// }
// return append(s, v)
// }
//TODO GO 1.8
// Len implement Sort Interface
// func (s VulnInfos) Len() int {
// return len(s)
// }
// // Swap implement Sort Interface
// func (s VulnInfos) Swap(i, j int) {
// s[i], s[j] = s[j], s[i]
// }
// // Less implement Sort Interface
// func (s VulnInfos) Less(i, j int) bool {
// return s[i].CveID < s[j].CveID
// }
// VulnInfo holds a vulnerability information and unsecure packages
type VulnInfo struct {
CveID string
@@ -412,6 +446,7 @@ type VulnInfo struct {
Packages PackageInfoList
DistroAdvisories []DistroAdvisory // for Aamazon, RHEL, FreeBSD
CpeNames []string
CveContents CveContents
}
// NilSliceToEmpty set nil slice fields to empty slice to avoid null in JSON
@@ -427,167 +462,132 @@ func (v *VulnInfo) NilSliceToEmpty() {
}
}
// FindByCveID find by CVEID
func (s VulnInfos) FindByCveID(cveID string) (VulnInfo, bool) {
for _, p := range s {
if cveID == p.CveID {
return p, true
}
}
return VulnInfo{CveID: cveID}, false
}
// immutable
func (s VulnInfos) set(cveID string, v VulnInfo) VulnInfos {
for i, p := range s {
if cveID == p.CveID {
s[i] = v
return s
}
}
return append(s, v)
}
// Len implement Sort Interface
func (s VulnInfos) Len() int {
return len(s)
}
// Swap implement Sort Interface
func (s VulnInfos) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
// Less implement Sort Interface
func (s VulnInfos) Less(i, j int) bool {
return s[i].CveID < s[j].CveID
}
// CveInfos is for sorting
type CveInfos []CveInfo
// type CveInfos []CveInfo
func (c CveInfos) Len() int {
return len(c)
}
// func (c CveInfos) Len() int {
// return len(c)
// }
func (c CveInfos) Swap(i, j int) {
c[i], c[j] = c[j], c[i]
}
// func (c CveInfos) Swap(i, j int) {
// c[i], c[j] = c[j], c[i]
// }
func (c CveInfos) Less(i, j int) bool {
if c[i].CvssV2Score() == c[j].CvssV2Score() {
return c[i].CveID < c[j].CveID
}
return c[j].CvssV2Score() < c[i].CvssV2Score()
}
// func (c CveInfos) Less(i, j int) bool {
// if c[i].CvssV2Score() == c[j].CvssV2Score() {
// return c[i].CveID < c[j].CveID
// }
// return c[j].CvssV2Score() < c[i].CvssV2Score()
// }
// Get cveInfo by cveID
func (c CveInfos) Get(cveID string) (CveInfo, bool) {
for _, cve := range c {
if cve.VulnInfo.CveID == cveID {
return cve, true
}
}
return CveInfo{}, false
}
// // Get cveInfo by cveID
// func (c CveInfos) Get(cveID string) (CveInfo, bool) {
// for _, cve := range c {
// if cve.VulnInfo.CveID == cveID {
// return cve, true
// }
// }
// return CveInfo{}, false
// }
// Delete by cveID
func (c *CveInfos) Delete(cveID string) {
cveInfos := *c
for i, cve := range cveInfos {
if cve.VulnInfo.CveID == cveID {
*c = append(cveInfos[:i], cveInfos[i+1:]...)
break
}
}
}
// // Delete by cveID
// func (c *CveInfos) Delete(cveID string) {
// cveInfos := *c
// for i, cve := range cveInfos {
// if cve.VulnInfo.CveID == cveID {
// *c = append(cveInfos[:i], cveInfos[i+1:]...)
// break
// }
// }
// }
// Insert cveInfo
func (c *CveInfos) Insert(cveInfo CveInfo) {
*c = append(*c, cveInfo)
}
// // Insert cveInfo
// func (c *CveInfos) Insert(cveInfo CveInfo) {
// *c = append(*c, cveInfo)
// }
// Update cveInfo
func (c CveInfos) Update(cveInfo CveInfo) (ok bool) {
for i, cve := range c {
if cve.VulnInfo.CveID == cveInfo.VulnInfo.CveID {
c[i] = cveInfo
return true
}
}
return false
}
// // Update cveInfo
// func (c CveInfos) Update(cveInfo CveInfo) (ok bool) {
// for i, cve := range c {
// if cve.VulnInfo.CveID == cveInfo.VulnInfo.CveID {
// c[i] = cveInfo
// return true
// }
// }
// return false
// }
// Upsert cveInfo
func (c *CveInfos) Upsert(cveInfo CveInfo) {
ok := c.Update(cveInfo)
if !ok {
c.Insert(cveInfo)
}
}
// // Upsert cveInfo
// func (c *CveInfos) Upsert(cveInfo CveInfo) {
// ok := c.Update(cveInfo)
// if !ok {
// c.Insert(cveInfo)
// }
// }
//TODO
// CveInfo has CVE detailed Information.
type CveInfo struct {
VulnInfo
CveContents []CveContent
}
// type CveInfo struct {
// VulnInfo
// CveContents []CveContent
// }
// Get a CveContent specified by arg
func (c *CveInfo) Get(typestr CveContentType) (*CveContent, bool) {
for _, cont := range c.CveContents {
if cont.Type == typestr {
return &cont, true
}
}
return &CveContent{}, false
}
// func (c *CveInfo) Get(typestr CveContentType) (*CveContent, bool) {
// for _, cont := range c.CveContents {
// if cont.Type == typestr {
// return &cont, true
// }
// }
// return &CveContent{}, false
// }
// Insert a CveContent to specified by arg
func (c *CveInfo) Insert(con CveContent) {
c.CveContents = append(c.CveContents, con)
}
// // Insert a CveContent to specified by arg
// func (c *CveInfo) Insert(con CveContent) {
// c.CveContents = append(c.CveContents, con)
// }
// Update a CveContent to specified by arg
func (c *CveInfo) Update(to CveContent) bool {
for i, cont := range c.CveContents {
if cont.Type == to.Type {
c.CveContents[i] = to
return true
}
}
return false
}
// // Update a CveContent to specified by arg
// func (c *CveInfo) Update(to CveContent) bool {
// for i, cont := range c.CveContents {
// if cont.Type == to.Type {
// c.CveContents[i] = to
// return true
// }
// }
// return false
// }
// CvssV2Score returns CVSS V2 Score
func (c *CveInfo) CvssV2Score() float64 {
//TODO
if cont, found := c.Get(NVD); found {
return cont.Cvss2Score
} else if cont, found := c.Get(JVN); found {
return cont.Cvss2Score
} else if cont, found := c.Get(RedHat); found {
return cont.Cvss2Score
}
return -1
}
// // CvssV2Score returns CVSS V2 Score
// func (c *CveInfo) CvssV2Score() float64 {
// //TODO
// if cont, found := c.Get(NVD); found {
// return cont.Cvss2Score
// } else if cont, found := c.Get(JVN); found {
// return cont.Cvss2Score
// } else if cont, found := c.Get(RedHat); found {
// return cont.Cvss2Score
// }
// return -1
// }
// NilSliceToEmpty set nil slice fields to empty slice to avoid null in JSON
func (c *CveInfo) NilSliceToEmpty() {
return
// TODO
// if c.CveDetail.Nvd.Cpes == nil {
// c.CveDetail.Nvd.Cpes = []cve.Cpe{}
// }
// if c.CveDetail.Jvn.Cpes == nil {
// c.CveDetail.Jvn.Cpes = []cve.Cpe{}
// }
// if c.CveDetail.Nvd.References == nil {
// c.CveDetail.Nvd.References = []cve.Reference{}
// }
// if c.CveDetail.Jvn.References == nil {
// c.CveDetail.Jvn.References = []cve.Reference{}
// }
}
// // NilSliceToEmpty set nil slice fields to empty slice to avoid null in JSON
// func (c *CveInfo) NilSliceToEmpty() {
// return
// // TODO
// // if c.CveDetail.Nvd.Cpes == nil {
// // c.CveDetail.Nvd.Cpes = []cve.Cpe{}
// // }
// // if c.CveDetail.Jvn.Cpes == nil {
// // c.CveDetail.Jvn.Cpes = []cve.Cpe{}
// // }
// // if c.CveDetail.Nvd.References == nil {
// // c.CveDetail.Nvd.References = []cve.Reference{}
// // }
// // if c.CveDetail.Jvn.References == nil {
// // c.CveDetail.Jvn.References = []cve.Reference{}
// // }
// }
// CveContentType is a source of CVE information
type CveContentType string
@@ -612,6 +612,68 @@ const (
Ubuntu CveContentType = "ubuntu"
)
// CveContents has slice of CveContent
type CveContents []CveContent
// Get CveContent by cveID
// TODO Pointer
func (v *CveContents) Get(typestr CveContentType) (CveContent, bool) {
for _, vv := range *v {
if vv.Type == typestr {
return vv, true
}
}
return CveContent{}, false
}
// Delete by cveID
func (v *CveContents) Delete(typestr CveContentType) {
cveContents := *v
for i, cc := range cveContents {
if cc.Type == typestr {
*v = append(cveContents[:i], cveContents[i+1:]...)
break
}
}
}
// Insert CveContent
func (v *CveContents) Insert(cont CveContent) {
*v = append(*v, cont)
}
// Update VulnInfo
func (v *CveContents) Update(cont CveContent) (ok bool) {
for i, vv := range *v {
if vv.Type == cont.Type {
(*v)[i] = cont
return true
}
}
return false
}
// Upsert CveContent
func (v *CveContents) Upsert(cont CveContent) {
ok := v.Update(cont)
if !ok {
v.Insert(cont)
}
}
// CvssV2Score returns CVSS V2 Score
func (v *CveContents) CvssV2Score() float64 {
//TODO
if cont, found := v.Get(NVD); found {
return cont.Cvss2Score
} else if cont, found := v.Get(JVN); found {
return cont.Cvss2Score
} else if cont, found := v.Get(RedHat); found {
return cont.Cvss2Score
}
return -1
}
// CveContent has abstraction of various vulnerability information
type CveContent struct {
Type CveContentType
@@ -630,6 +692,11 @@ type CveContent struct {
LastModified time.Time
}
// Empty checks the content is empty
func (c CveContent) Empty() bool {
return c.Summary == ""
}
// Cpe is Common Platform Enumeration
type Cpe struct {
CpeName string

View File

@@ -59,64 +59,30 @@ func (o Debian) FillCveInfoFromOvalDB(r *models.ScanResult) (*models.ScanResult,
}
func (o Debian) fillOvalInfo(r *models.ScanResult, definition *ovalmodels.Definition) *models.ScanResult {
// Update ScannedCves by OVAL info
found := false
updatedCves := []models.VulnInfo{}
// Update scanned confidence to ovalmatch
for _, scanned := range r.ScannedCves {
if scanned.CveID == definition.Debian.CveID {
found = true
if scanned.Confidence.Score < models.OvalMatch.Score {
scanned.Confidence = models.OvalMatch
}
}
updatedCves = append(updatedCves, scanned)
}
vuln := models.VulnInfo{
CveID: definition.Debian.CveID,
Confidence: models.OvalMatch,
Packages: getPackageInfoList(r, definition),
}
if !found {
util.Log.Debugf("%s is newly detected by OVAL", vuln.CveID)
updatedCves = append(updatedCves, vuln)
}
r.ScannedCves = updatedCves
// Update KnownCves by OVAL info
ovalContent := *o.convertToModel(definition)
ovalContent.Type = models.CveContentType(r.Family)
cInfo, ok := r.KnownCves.Get(definition.Debian.CveID)
vinfo, ok := r.ScannedCves.Get(definition.Debian.CveID)
if !ok {
cInfo.VulnInfo = vuln
cInfo.CveContents = []models.CveContent{ovalContent}
}
if !cInfo.Update(ovalContent) {
cInfo.Insert(ovalContent)
}
if cInfo.VulnInfo.Confidence.Score < models.OvalMatch.Score {
cInfo.Confidence = models.OvalMatch
}
r.KnownCves.Upsert(cInfo)
// Update UnknownCves by OVAL info
cInfo, ok = r.UnknownCves.Get(definition.Debian.CveID)
if ok {
r.UnknownCves.Delete(definition.Debian.CveID)
// Insert new CveInfo
if !cInfo.Update(ovalContent) {
cInfo.Insert(ovalContent)
util.Log.Infof("%s is newly detected by OVAL",
definition.Debian.CveID)
vinfo = models.VulnInfo{
CveID: definition.Debian.CveID,
Confidence: models.OvalMatch,
Packages: getPackageInfoList(r, definition),
CveContents: []models.CveContent{ovalContent},
}
if cInfo.VulnInfo.Confidence.Score < models.OvalMatch.Score {
cInfo.Confidence = models.OvalMatch
} else {
if _, ok := vinfo.CveContents.Get(models.CveContentType(r.Family)); !ok {
util.Log.Infof("%s is also detected by OVAL", definition.Debian.CveID)
} else {
util.Log.Infof("%s will be updated by OVAL", definition.Debian.CveID)
}
r.KnownCves.Upsert(cInfo)
if vinfo.Confidence.Score < models.OvalMatch.Score {
vinfo.Confidence = models.OvalMatch
}
vinfo.CveContents.Upsert(ovalContent)
}
r.ScannedCves.Upsert(vinfo)
return r
}
@@ -133,6 +99,7 @@ func (o Debian) convertToModel(def *ovalmodels.Definition) *models.CveContent {
CveID: def.Debian.CveID,
Title: def.Title,
Summary: def.Description,
Severity: def.Advisory.Severity,
References: refs,
}
}

View File

@@ -2,6 +2,8 @@ package oval
import (
"fmt"
"strconv"
"strings"
"github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/models"
@@ -55,76 +57,26 @@ func (o Redhat) FillCveInfoFromOvalDB(r *models.ScanResult) (*models.ScanResult,
}
func (o Redhat) fillOvalInfo(r *models.ScanResult, definition *ovalmodels.Definition) *models.ScanResult {
cveIDSet := make(map[string]bool)
cveID2VulnInfo := make(map[string]models.VulnInfo)
for _, cve := range definition.Advisory.Cves {
cveIDSet[cve.CveID] = false
cveID2VulnInfo[cve.CveID] = models.VulnInfo{
CveID: cve.CveID,
Confidence: models.OvalMatch,
Packages: getPackageInfoList(r, definition),
}
}
// Update ScannedCves by OVAL info
updatedCves := []models.VulnInfo{}
for _, scanned := range r.ScannedCves {
// Update scanned confidence to ovalmatch
for _, c := range definition.Advisory.Cves {
if scanned.CveID == c.CveID {
cveIDSet[c.CveID] = true
if scanned.Confidence.Score < models.OvalMatch.Score {
scanned.Confidence = models.OvalMatch
}
break
}
}
updatedCves = append(updatedCves, scanned)
}
for cveID, found := range cveIDSet {
if !found {
util.Log.Debugf("%s is newly detected by OVAL", cveID)
updatedCves = append(updatedCves, cveID2VulnInfo[cveID])
}
}
r.ScannedCves = updatedCves
// Update KnownCves by OVAL info
for _, c := range definition.Advisory.Cves {
ovalContent := *o.convertToModel(c.CveID, definition)
cInfo, ok := r.KnownCves.Get(c.CveID)
ovalContent := *o.convertToModel(cve.CveID, definition)
vinfo, ok := r.ScannedCves.Get(cve.CveID)
if !ok {
cInfo.VulnInfo = cveID2VulnInfo[c.CveID]
cInfo.CveContents = []models.CveContent{ovalContent}
}
if !cInfo.Update(ovalContent) {
cInfo.Insert(ovalContent)
}
if cInfo.VulnInfo.Confidence.Score < models.OvalMatch.Score {
cInfo.Confidence = models.OvalMatch
}
r.KnownCves.Upsert(cInfo)
}
// Update UnknownCves by OVAL info
for _, c := range definition.Advisory.Cves {
cInfo, ok := r.UnknownCves.Get(c.CveID)
if ok {
r.UnknownCves.Delete(c.CveID)
// Insert new CveInfo
ovalContent := *o.convertToModel(c.CveID, definition)
if !cInfo.Update(ovalContent) {
cInfo.Insert(ovalContent)
util.Log.Infof("%s is newly detected by OVAL",
definition.Debian.CveID)
vinfo = models.VulnInfo{
CveID: cve.CveID,
Confidence: models.OvalMatch,
Packages: getPackageInfoList(r, definition),
CveContents: []models.CveContent{ovalContent},
}
if cInfo.VulnInfo.Confidence.Score < models.OvalMatch.Score {
cInfo.Confidence = models.OvalMatch
} else {
if vinfo.Confidence.Score < models.OvalMatch.Score {
vinfo.Confidence = models.OvalMatch
}
r.KnownCves.Upsert(cInfo)
vinfo.CveContents.Upsert(ovalContent)
}
r.ScannedCves.Upsert(vinfo)
}
return r
}
@@ -134,7 +86,6 @@ func (o Redhat) convertToModel(cveID string, def *ovalmodels.Definition) *models
continue
}
var refs []models.Reference
//TODO RHSAのリンクを入れる
for _, r := range def.References {
refs = append(refs, models.Reference{
Link: r.RefURL,
@@ -143,20 +94,52 @@ func (o Redhat) convertToModel(cveID string, def *ovalmodels.Definition) *models
})
}
// util.ParseCvss2()
score2, vec2 := o.parseCvss2(cve.Cvss2)
score3, vec3 := o.parseCvss3(cve.Cvss3)
return &models.CveContent{
Type: models.RedHat,
CveID: cve.CveID,
Title: def.Title,
Summary: def.Description,
Severity: def.Advisory.Severity,
// V2Score: v2Score, // TODO divide into score and vector
Cvss2Vector: cve.Cvss2, // TODO divide into score and vector
Cvss3Vector: cve.Cvss3, // TODO divide into score and vector
References: refs,
CweID: cve.Cwe,
Type: models.RedHat,
CveID: cve.CveID,
Title: def.Title,
Summary: def.Description,
Severity: def.Advisory.Severity,
Cvss2Score: score2,
Cvss2Vector: vec2,
Cvss3Score: score3,
Cvss3Vector: vec3,
References: refs,
CweID: cve.Cwe,
Published: def.Advisory.Issued,
LastModified: def.Advisory.Updated,
}
}
return nil
}
// ParseCvss2 divide CVSSv2 string into score and vector
// 5/AV:N/AC:L/Au:N/C:N/I:N/A:P
func (o Redhat) parseCvss2(scoreVector string) (score float64, vector string) {
var err error
ss := strings.Split(scoreVector, "/")
if 1 < len(ss) {
if score, err = strconv.ParseFloat(ss[0], 64); err != nil {
return 0, ""
}
return score, strings.Join(ss[1:len(ss)], "/")
}
return 0, ""
}
// ParseCvss3 divide CVSSv3 string into score and vector
// 5.6/CVSS:3.0/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:L
func (o Redhat) parseCvss3(scoreVector string) (score float64, vector string) {
var err error
ss := strings.Split(scoreVector, "/CVSS:3.0/")
if 1 < len(ss) {
if score, err = strconv.ParseFloat(ss[0], 64); err != nil {
return 0, ""
}
return score, strings.Join(ss[1:len(ss)], "/")
}
return 0, ""
}

69
oval/redhat_test.go Normal file
View File

@@ -0,0 +1,69 @@
package oval
import "testing"
func TestParseCvss2(t *testing.T) {
type out struct {
score float64
vector string
}
var tests = []struct {
in string
out out
}{
{
in: "5/AV:N/AC:L/Au:N/C:N/I:N/A:P",
out: out{
score: 5.0,
vector: "AV:N/AC:L/Au:N/C:N/I:N/A:P",
},
},
{
in: "",
out: out{
score: 0,
vector: "",
},
},
}
for _, tt := range tests {
s, v := Redhat{}.parseCvss2(tt.in)
if s != tt.out.score || v != tt.out.vector {
t.Errorf("\nexpected: %f, %s\n actual: %f, %s",
tt.out.score, tt.out.vector, s, v)
}
}
}
func TestParseCvss3(t *testing.T) {
type out struct {
score float64
vector string
}
var tests = []struct {
in string
out out
}{
{
in: "5.6/CVSS:3.0/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:L",
out: out{
score: 5.6,
vector: "AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:L",
},
},
{
in: "",
out: out{
score: 0,
vector: "",
},
},
}
for _, tt := range tests {
s, v := Redhat{}.parseCvss3(tt.in)
if s != tt.out.score || v != tt.out.vector {
t.Errorf("\nexpected: %f, %s\n actual: %f, %s",
tt.out.score, tt.out.vector, s, v)
}
}
}

View File

@@ -139,13 +139,9 @@ func createBlockBlob(cli storage.BlobStorageClient, k string, b []byte) error {
k = k + ".gz"
}
if err := cli.CreateBlockBlobFromReader(
c.Conf.AzureContainer,
k,
uint64(len(b)),
bytes.NewReader(b),
map[string]string{},
); err != nil {
ref := cli.GetContainerReference(c.Conf.AzureContainer)
blob := ref.GetBlobReference(k)
if err := blob.CreateBlockBlobFromReader(bytes.NewReader(b), nil); err != nil {
return fmt.Errorf("Failed to upload data to %s/%s, %s",
c.Conf.AzureContainer, k, err)
}

View File

@@ -41,8 +41,8 @@ func (w EMailWriter) Write(rs ...models.ScanResult) (err error) {
for _, r := range rs {
if conf.FormatOneEMail {
message += formatFullPlainText(r) + "\r\n\r\n"
totalResult.KnownCves = append(totalResult.KnownCves, r.KnownCves...)
totalResult.UnknownCves = append(totalResult.UnknownCves, r.UnknownCves...)
// totalResult.KnownCves = append(totalResult.KnownCves, r.KnownCves...)
// totalResult.UnknownCves = append(totalResult.UnknownCves, r.UnknownCves...)
} else {
var subject string
if len(r.Errors) != 0 {

View File

@@ -21,7 +21,6 @@ import (
"encoding/json"
"fmt"
"sort"
"strings"
"time"
log "github.com/Sirupsen/logrus"
@@ -67,11 +66,12 @@ func (w SlackWriter) Write(rs ...models.ScanResult) error {
}
if 0 < len(r.Errors) {
serverInfo := fmt.Sprintf("*%s*", r.ServerInfo())
notifyUsers := getNotifyUsers(config.Conf.Slack.NotifyUsers)
txt := fmt.Sprintf("%s\n%s\nError: %s", notifyUsers, serverInfo, r.Errors)
//TODO
// serverInfo := fmt.Sprintf("*%s*", r.ServerInfo())
// notifyUsers := getNotifyUsers(config.Conf.Slack.NotifyUsers)
// txt := fmt.Sprintf("%s\n%s\nError: %s", notifyUsers, serverInfo, r.Errors)
msg := message{
Text: txt,
// Text: txt,
Username: conf.AuthUser,
IconEmoji: conf.IconEmoji,
Channel: channel,
@@ -152,57 +152,57 @@ func send(msg message) error {
func msgText(r models.ScanResult) string {
notifyUsers := ""
if 0 < len(r.KnownCves) || 0 < len(r.UnknownCves) {
notifyUsers = getNotifyUsers(config.Conf.Slack.NotifyUsers)
}
// if 0 < len(r.KnownCves) || 0 < len(r.UnknownCves) {
// notifyUsers = getNotifyUsers(config.Conf.Slack.NotifyUsers)
// }
serverInfo := fmt.Sprintf("*%s*", r.ServerInfo())
return fmt.Sprintf("%s\n%s\n>%s", notifyUsers, serverInfo, r.CveSummary())
}
func toSlackAttachments(scanResult models.ScanResult) (attaches []*attachment) {
cves := scanResult.KnownCves
if !config.Conf.IgnoreUnscoredCves {
cves = append(cves, scanResult.UnknownCves...)
}
// cves := scanResult.KnownCves
// if !config.Conf.IgnoreUnscoredCves {
// cves = append(cves, scanResult.UnknownCves...)
// }
for _, cveInfo := range cves {
cveID := cveInfo.VulnInfo.CveID
// for _, cveInfo := range cves {
// cveID := cveInfo.VulnInfo.CveID
curentPackages := []string{}
for _, p := range cveInfo.Packages {
curentPackages = append(curentPackages, p.FormatCurrentVer())
}
for _, n := range cveInfo.CpeNames {
curentPackages = append(curentPackages, n)
}
// curentPackages := []string{}
// for _, p := range cveInfo.Packages {
// curentPackages = append(curentPackages, p.FormatCurrentVer())
// }
// for _, n := range cveInfo.CpeNames {
// curentPackages = append(curentPackages, n)
// }
newPackages := []string{}
for _, p := range cveInfo.Packages {
newPackages = append(newPackages, p.FormatNewVer())
}
// newPackages := []string{}
// for _, p := range cveInfo.Packages {
// newPackages = append(newPackages, p.FormatNewVer())
// }
a := attachment{
Title: cveID,
TitleLink: fmt.Sprintf("%s/%s", nvdBaseURL, cveID),
Text: attachmentText(cveInfo, scanResult.Family),
MrkdwnIn: []string{"text", "pretext"},
Fields: []*field{
{
// Title: "Current Package/CPE",
Title: "Installed",
Value: strings.Join(curentPackages, "\n"),
Short: true,
},
{
Title: "Candidate",
Value: strings.Join(newPackages, "\n"),
Short: true,
},
},
Color: color(cveInfo.CvssV2Score()),
}
attaches = append(attaches, &a)
}
// a := attachment{
// Title: cveID,
// TitleLink: fmt.Sprintf("%s/%s", nvdBaseURL, cveID),
// Text: attachmentText(cveInfo, scanResult.Family),
// MrkdwnIn: []string{"text", "pretext"},
// Fields: []*field{
// {
// // Title: "Current Package/CPE",
// Title: "Installed",
// Value: strings.Join(curentPackages, "\n"),
// Short: true,
// },
// {
// Title: "Candidate",
// Value: strings.Join(newPackages, "\n"),
// Short: true,
// },
// },
// Color: color(cveInfo.CvssV2Score()),
// }
// attaches = append(attaches, &a)
// }
return
}
@@ -220,80 +220,80 @@ func color(cvssScore float64) string {
}
}
func attachmentText(cveInfo models.CveInfo, osFamily string) string {
// linkText := links(cveInfo, osFamily)
//TODO
return ""
// switch {
// case config.Conf.Lang == "ja" &&
// 0 < cveInfo.CveDetail.Jvn.CvssScore():
// func attachmentText(cveInfo models.CveInfo, osFamily string) string {
// linkText := links(cveInfo, osFamily)
//TODO
// return ""
// switch {
// case config.Conf.Lang == "ja" &&
// 0 < cveInfo.CveDetail.Jvn.CvssScore():
// jvn := cveInfo.CveDetail.Jvn
// return fmt.Sprintf("*%4.1f (%s)* <%s|%s>\n%s\n%s\n*Confidence:* %v",
// cveInfo.CveDetail.CvssScore(config.Conf.Lang),
// jvn.CvssSeverity(),
// fmt.Sprintf(cvssV2CalcBaseURL, cveInfo.CveDetail.CveID),
// jvn.CvssVector(),
// jvn.CveTitle(),
// linkText,
// cveInfo.VulnInfo.Confidence,
// )
// case 0 < cveInfo.CveDetail.CvssScore("en"):
// nvd := cveInfo.CveDetail.Nvd
// return fmt.Sprintf("*%4.1f (%s)* <%s|%s>\n%s\n%s\n*Confidence:* %v",
// cveInfo.CveDetail.CvssScore(config.Conf.Lang),
// nvd.CvssSeverity(),
// fmt.Sprintf(cvssV2CalcBaseURL, cveInfo.CveDetail.CveID),
// nvd.CvssVector(),
// nvd.CveSummary(),
// linkText,
// cveInfo.VulnInfo.Confidence,
// )
// default:
// nvd := cveInfo.CveDetail.Nvd
// return fmt.Sprintf("?\n%s\n%s\n*Confidence:* %v",
// nvd.CveSummary(), linkText, cveInfo.VulnInfo.Confidence)
// }
}
// jvn := cveInfo.CveDetail.Jvn
// return fmt.Sprintf("*%4.1f (%s)* <%s|%s>\n%s\n%s\n*Confidence:* %v",
// cveInfo.CveDetail.CvssScore(config.Conf.Lang),
// jvn.CvssSeverity(),
// fmt.Sprintf(cvssV2CalcBaseURL, cveInfo.CveDetail.CveID),
// jvn.CvssVector(),
// jvn.CveTitle(),
// linkText,
// cveInfo.VulnInfo.Confidence,
// )
// case 0 < cveInfo.CveDetail.CvssScore("en"):
// nvd := cveInfo.CveDetail.Nvd
// return fmt.Sprintf("*%4.1f (%s)* <%s|%s>\n%s\n%s\n*Confidence:* %v",
// cveInfo.CveDetail.CvssScore(config.Conf.Lang),
// nvd.CvssSeverity(),
// fmt.Sprintf(cvssV2CalcBaseURL, cveInfo.CveDetail.CveID),
// nvd.CvssVector(),
// nvd.CveSummary(),
// linkText,
// cveInfo.VulnInfo.Confidence,
// )
// default:
// nvd := cveInfo.CveDetail.Nvd
// return fmt.Sprintf("?\n%s\n%s\n*Confidence:* %v",
// nvd.CveSummary(), linkText, cveInfo.VulnInfo.Confidence)
// }
// }
func links(cveInfo models.CveInfo, osFamily string) string {
links := []string{}
// func links(cveInfo models.CveInfo, osFamily string) string {
// links := []string{}
//TODO
// cweID := cveInfo.CveDetail.CweID()
// if 0 < len(cweID) {
// links = append(links, fmt.Sprintf("<%s|%s>",
// cweURL(cweID), cweID))
// if config.Conf.Lang == "ja" {
// links = append(links, fmt.Sprintf("<%s|%s(JVN)>",
// cweJvnURL(cweID), cweID))
// }
// }
// //TODO
// // cweID := cveInfo.CveDetail.CweID()
// // if 0 < len(cweID) {
// // links = append(links, fmt.Sprintf("<%s|%s>",
// // cweURL(cweID), cweID))
// // if config.Conf.Lang == "ja" {
// // links = append(links, fmt.Sprintf("<%s|%s(JVN)>",
// // cweJvnURL(cweID), cweID))
// // }
// // }
cveID := cveInfo.VulnInfo.CveID
//TODO
// if config.Conf.Lang == "ja" && 0 < len(cveInfo.CveDetail.Jvn.Link()) {
// jvn := fmt.Sprintf("<%s|JVN>", cveInfo.CveDetail.Jvn.Link())
// links = append(links, jvn)
// }
dlinks := distroLinks(cveInfo, osFamily)
for _, link := range dlinks {
links = append(links,
fmt.Sprintf("<%s|%s>", link.url, link.title))
}
links = append(links, fmt.Sprintf("<%s|MITRE>",
fmt.Sprintf("%s%s", mitreBaseURL, cveID)))
links = append(links, fmt.Sprintf("<%s|CVEDetails>",
fmt.Sprintf("%s/%s", cveDetailsBaseURL, cveID)))
// cveID := cveInfo.VulnInfo.CveID
// //TODO
// // if config.Conf.Lang == "ja" && 0 < len(cveInfo.CveDetail.Jvn.Link()) {
// // jvn := fmt.Sprintf("<%s|JVN>", cveInfo.CveDetail.Jvn.Link())
// // links = append(links, jvn)
// // }
// dlinks := distroLinks(cveInfo, osFamily)
// for _, link := range dlinks {
// links = append(links,
// fmt.Sprintf("<%s|%s>", link.url, link.title))
// }
// links = append(links, fmt.Sprintf("<%s|MITRE>",
// fmt.Sprintf("%s%s", mitreBaseURL, cveID)))
// links = append(links, fmt.Sprintf("<%s|CVEDetails>",
// fmt.Sprintf("%s/%s", cveDetailsBaseURL, cveID)))
return strings.Join(links, " / ")
}
// return strings.Join(links, " / ")
// }
// See testcase
func getNotifyUsers(notifyUsers []string) string {
slackStyleTexts := []string{}
for _, username := range notifyUsers {
slackStyleTexts = append(slackStyleTexts, fmt.Sprintf("<%s>", username))
}
return strings.Join(slackStyleTexts, " ")
}
// // See testcase
// func getNotifyUsers(notifyUsers []string) string {
// slackStyleTexts := []string{}
// for _, username := range notifyUsers {
// slackStyleTexts = append(slackStyleTexts, fmt.Sprintf("<%s>", username))
// }
// return strings.Join(slackStyleTexts, " ")
// }

View File

@@ -22,7 +22,6 @@ import (
"fmt"
"os"
"strings"
"text/template"
"time"
log "github.com/Sirupsen/logrus"
@@ -221,7 +220,8 @@ func movable(v *gocui.View, nextY int) (ok bool, yLimit int) {
}
return true, yLimit
case "summary":
yLimit = len(currentScanResult.AllCves()) - 1
//TODO
// yLimit = len(currentScanResult.AllCves()) - 1
if yLimit < nextY {
return false, yLimit
}
@@ -601,71 +601,72 @@ func summaryLines() string {
return "Error: Scan with --debug to view the details"
}
indexFormat := ""
if len(currentScanResult.AllCves()) < 10 {
indexFormat = "[%1d]"
} else if len(currentScanResult.AllCves()) < 100 {
indexFormat = "[%2d]"
} else {
indexFormat = "[%3d]"
}
//TODO
// indexFormat := ""
// if len(currentScanResult.AllCves()) < 10 {
// indexFormat = "[%1d]"
// } else if len(currentScanResult.AllCves()) < 100 {
// indexFormat = "[%2d]"
// } else {
// indexFormat = "[%3d]"
// }
for i, d := range currentScanResult.AllCves() {
var cols []string
//TODO
var summary string
if cont, found := d.Get(models.NVD); found {
summary = cont.Summary
}
var cvssScore string
if d.CvssV2Score() <= 0 {
cvssScore = "| ?"
} else {
cvssScore = fmt.Sprintf("| %4.1f", d.CvssV2Score())
}
cols = []string{
fmt.Sprintf(indexFormat, i+1),
d.VulnInfo.CveID,
cvssScore,
fmt.Sprintf("| %3d |", d.VulnInfo.Confidence.Score),
summary,
}
// if config.Conf.Lang == "ja" && 0 < d.CveDetail.Jvn.CvssScore() {
// summary := d.CveDetail.Jvn.CveTitle()
// cols = []string{
// fmt.Sprintf(indexFormat, i+1),
// d.CveDetail.CveID,
// fmt.Sprintf("| %4.1f",
// d.CveDetail.CvssScore(config.Conf.Lang)),
// fmt.Sprintf("| %3d |", d.VulnInfo.Confidence.Score),
// summary,
// }
// } else {
// summary := d.CveDetail.Nvd.CveSummary()
// for i, d := range currentScanResult.AllCves() {
// var cols []string
// //TODO
// var summary string
// if cont, found := d.Get(models.NVD); found {
// summary = cont.Summary
// }
// var cvssScore string
// if d.CvssV2Score() <= 0 {
// cvssScore = "| ?"
// } else {
// cvssScore = fmt.Sprintf("| %4.1f", d.CvssV2Score())
// }
// cols = []string{
// fmt.Sprintf(indexFormat, i+1),
// d.VulnInfo.CveID,
// cvssScore,
// fmt.Sprintf("| %3d |", d.VulnInfo.Confidence.Score),
// summary,
// }
// // if config.Conf.Lang == "ja" && 0 < d.CveDetail.Jvn.CvssScore() {
// // summary := d.CveDetail.Jvn.CveTitle()
// // cols = []string{
// // fmt.Sprintf(indexFormat, i+1),
// // d.CveDetail.CveID,
// // fmt.Sprintf("| %4.1f",
// // d.CveDetail.CvssScore(config.Conf.Lang)),
// // fmt.Sprintf("| %3d |", d.VulnInfo.Confidence.Score),
// // summary,
// // }
// // } else {
// // summary := d.CveDetail.Nvd.CveSummary()
// var cvssScore string
// if d.CveDetail.CvssScore("en") <= 0 {
// cvssScore = "| ?"
// } else {
// cvssScore = fmt.Sprintf("| %4.1f",
// d.CveDetail.CvssScore(config.Conf.Lang))
// }
// // var cvssScore string
// // if d.CveDetail.CvssScore("en") <= 0 {
// // cvssScore = "| ?"
// // } else {
// // cvssScore = fmt.Sprintf("| %4.1f",
// // d.CveDetail.CvssScore(config.Conf.Lang))
// // }
// cols = []string{
// fmt.Sprintf(indexFormat, i+1),
// d.CveDetail.CveID,
// cvssScore,
// fmt.Sprintf("| %3d |", d.VulnInfo.Confidence.Score),
// summary,
// }
// }
// // cols = []string{
// // fmt.Sprintf(indexFormat, i+1),
// // d.CveDetail.CveID,
// // cvssScore,
// // fmt.Sprintf("| %3d |", d.VulnInfo.Confidence.Score),
// // summary,
// // }
// // }
icols := make([]interface{}, len(cols))
for j := range cols {
icols[j] = cols[j]
}
stable.AddRow(icols...)
}
// icols := make([]interface{}, len(cols))
// for j := range cols {
// icols[j] = cols[j]
// }
// stable.AddRow(icols...)
// }
return fmt.Sprintf("%s", stable)
}
@@ -712,19 +713,21 @@ func setChangelogLayout(g *gocui.Gui) error {
if err != gocui.ErrUnknownView {
return err
}
if len(currentScanResult.Errors) != 0 || len(currentScanResult.AllCves()) == 0 {
return nil
}
//TODO
// if len(currentScanResult.Errors) != 0 || len(currentScanResult.AllCves()) == 0 {
// return nil
// }
lines := []string{}
cveInfo := currentScanResult.AllCves()[currentCveInfo]
for _, pack := range cveInfo.Packages {
for _, p := range currentScanResult.Packages {
if pack.Name == p.Name {
lines = append(lines, formatOneChangelog(p), "\n")
}
}
}
//TODO
// cveInfo := currentScanResult.AllCves()[currentCveInfo]
// for _, pack := range cveInfo.Packages {
// for _, p := range currentScanResult.Packages {
// if pack.Name == p.Name {
// lines = append(lines, formatOneChangelog(p), "\n")
// }
// }
// }
text := strings.Join(lines, "\n")
fmt.Fprint(v, text)
v.Editable = false
@@ -756,20 +759,20 @@ func detailLines() (string, error) {
return "", nil
}
if len(currentScanResult.AllCves()) == 0 {
return "No vulnerable packages", nil
}
//TODO
// if len(currentScanResult.AllCves()) == 0 {
// return "No vulnerable packages", nil
// }
// cveInfo := currentScanResult.AllCves()[currentCveInfo]
// cveID := cveInfo.VulnInfo.CveID
cveInfo := currentScanResult.AllCves()[currentCveInfo]
cveID := cveInfo.VulnInfo.CveID
// tmpl, err := template.New("detail").Parse(detailTemplate())
// if err != nil {
// return "", err
// }
tmpl, err := template.New("detail").Parse(detailTemplate())
if err != nil {
return "", err
}
var cvssSeverity, cvssVector, summary string
var refs []cve.Reference
// var cvssSeverity, cvssVector, summary string
// var refs []cve.Reference
switch {
//TODO
// case config.Conf.Lang == "ja" &&
@@ -780,67 +783,67 @@ func detailLines() (string, error) {
// summary = fmt.Sprintf("%s\n%s", jvn.CveTitle(), jvn.CveSummary())
// refs = jvn.VulnSiteReferences()
default:
var nvd *models.CveContent
if cont, found := cveInfo.Get(models.NVD); found {
nvd = cont
}
// var nvd *models.CveContent
//TODO
// if cont, found := cveInfo.Get(models.NVD); found {
// nvd = cont
// }
// cvssSeverity = nvd.CvssSeverity()
// cvssVector = nvd.CvssVector()
summary = nvd.Summary
// summary = nvd.Summary
// refs = nvd.VulnSiteReferences()
}
//TODO
// cweURL := cweURL(cveInfo.CveDetail.CweID())
links := []string{
fmt.Sprintf("[NVD]( %s )", fmt.Sprintf("%s/%s", nvdBaseURL, cveID)),
fmt.Sprintf("[MITRE]( %s )", fmt.Sprintf("%s%s", mitreBaseURL, cveID)),
fmt.Sprintf("[CveDetais]( %s )", fmt.Sprintf("%s/%s", cveDetailsBaseURL, cveID)),
fmt.Sprintf("[CVSSv2 Calc]( %s )", fmt.Sprintf(cvssV2CalcBaseURL, cveID)),
fmt.Sprintf("[CVSSv3 Calc]( %s )", fmt.Sprintf(cvssV3CalcBaseURL, cveID)),
}
dlinks := distroLinks(cveInfo, currentScanResult.Family)
for _, link := range dlinks {
links = append(links, fmt.Sprintf("[%s]( %s )", link.title, link.url))
}
// links := []string{
// fmt.Sprintf("[NVD]( %s )", fmt.Sprintf("%s/%s", nvdBaseURL, cveID)),
// fmt.Sprintf("[MITRE]( %s )", fmt.Sprintf("%s%s", mitreBaseURL, cveID)),
// fmt.Sprintf("[CveDetais]( %s )", fmt.Sprintf("%s/%s", cveDetailsBaseURL, cveID)),
// fmt.Sprintf("[CVSSv2 Calc]( %s )", fmt.Sprintf(cvssV2CalcBaseURL, cveID)),
// fmt.Sprintf("[CVSSv3 Calc]( %s )", fmt.Sprintf(cvssV3CalcBaseURL, cveID)),
// }
// dlinks := distroLinks(cveInfo, currentScanResult.Family)
// for _, link := range dlinks {
// links = append(links, fmt.Sprintf("[%s]( %s )", link.title, link.url))
// }
//TODO
var cvssScore string
if cveInfo.CvssV2Score() == -1 {
cvssScore = "?"
// } else {
// cvssScore = fmt.Sprintf("%4.1f", cveInfo.CveDetail.CvssScore(config.Conf.Lang))
}
// var cvssScore string
// if cveInfo.CvssV2Score() == -1 {
// cvssScore = "?"
// // } else {
// // cvssScore = fmt.Sprintf("%4.1f", cveInfo.CveDetail.CvssScore(config.Conf.Lang))
// }
packages := []string{}
for _, pack := range cveInfo.Packages {
packages = append(packages,
fmt.Sprintf(
"%s -> %s",
pack.FormatCurrentVer(),
pack.FormatNewVer()))
}
// packages := []string{}
// for _, pack := range cveInfo.Packages {
// packages = append(packages,
// fmt.Sprintf(
// "%s -> %s",
// pack.FormatCurrentVer(),
// pack.FormatNewVer()))
// }
data := dataForTmpl{
CveID: cveID,
CvssScore: cvssScore,
CvssSeverity: cvssSeverity,
CvssVector: cvssVector,
Summary: summary,
Confidence: cveInfo.VulnInfo.Confidence,
//TODO
// CweURL: cweURL,
VulnSiteLinks: links,
References: refs,
Packages: packages,
CpeNames: cveInfo.CpeNames,
}
// data := dataForTmpl{
// CveID: cveID,
// CvssScore: cvssScore,
// CvssSeverity: cvssSeverity,
// CvssVector: cvssVector,
// Summary: summary,
// Confidence: cveInfo.VulnInfo.Confidence,
// //TODO
// // CweURL: cweURL,
// VulnSiteLinks: links,
// References: refs,
// Packages: packages,
// CpeNames: cveInfo.CpeNames,
// }
buf := bytes.NewBuffer(nil) // create empty buffer
if err := tmpl.Execute(buf, data); err != nil {
return "", err
}
// if err := tmpl.Execute(buf, data); err != nil {
// return "", err
// }
return string(buf.Bytes()), nil
}

View File

@@ -22,7 +22,6 @@ import (
"fmt"
"strings"
"github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/models"
"github.com/gosuri/uitable"
)
@@ -84,10 +83,11 @@ func formatShortPlainText(r models.ScanResult) string {
stable.MaxColWidth = maxColWidth
stable.Wrap = true
cves := r.KnownCves
if !config.Conf.IgnoreUnscoredCves {
cves = append(cves, r.UnknownCves...)
}
//TODO
// cves := r.KnownCves
// if !config.Conf.IgnoreUnscoredCves {
// cves = append(cves, r.UnknownCves...)
// }
var buf bytes.Buffer
for i := 0; i < len(r.ServerInfo()); i++ {
@@ -106,83 +106,84 @@ func formatShortPlainText(r models.ScanResult) string {
header, r.Errors)
}
if len(cves) == 0 {
return fmt.Sprintf(`
%s
No CVE-IDs are found in updatable packages.
%s
`, header, r.Packages.FormatUpdatablePacksSummary())
}
//TODO
// if len(cves) == 0 {
// return fmt.Sprintf(`
// %s
// No CVE-IDs are found in updatable packages.
// %s
// `, header, r.Packages.FormatUpdatablePacksSummary())
// }
for _, d := range cves {
var packsVer string
for _, p := range d.Packages {
packsVer += fmt.Sprintf(
"%s -> %s\n", p.FormatCurrentVer(), p.FormatNewVer())
}
for _, n := range d.CpeNames {
packsVer += n
}
// for _, d := range cves {
// var packsVer string
// for _, p := range d.Packages {
// packsVer += fmt.Sprintf(
// "%s -> %s\n", p.FormatCurrentVer(), p.FormatNewVer())
// }
// for _, n := range d.CpeNames {
// packsVer += n
// }
var scols []string
switch {
// case config.Conf.Lang == "ja" &&
//TODO
// 0 < d.CveDetail.Jvn.CvssScore():
// summary := fmt.Sprintf("%s\n%s\n%s\n%sConfidence: %v",
// d.CveDetail.Jvn.CveTitle(),
// d.CveDetail.Jvn.Link(),
// distroLinks(d, r.Family)[0].url,
// packsVer,
// d.VulnInfo.Confidence,
// )
// scols = []string{
// d.CveDetail.CveID,
// fmt.Sprintf("%-4.1f (%s)",
// d.CveDetail.CvssScore(config.Conf.Lang),
// d.CveDetail.Jvn.CvssSeverity(),
// ),
// summary,
// }
// var scols []string
// switch {
// // case config.Conf.Lang == "ja" &&
// //TODO
// // 0 < d.CveDetail.Jvn.CvssScore():
// // summary := fmt.Sprintf("%s\n%s\n%s\n%sConfidence: %v",
// // d.CveDetail.Jvn.CveTitle(),
// // d.CveDetail.Jvn.Link(),
// // distroLinks(d, r.Family)[0].url,
// // packsVer,
// // d.VulnInfo.Confidence,
// // )
// // scols = []string{
// // d.CveDetail.CveID,
// // fmt.Sprintf("%-4.1f (%s)",
// // d.CveDetail.CvssScore(config.Conf.Lang),
// // d.CveDetail.Jvn.CvssSeverity(),
// // ),
// // summary,
// // }
case 0 < d.CvssV2Score():
var nvd *models.CveContent
if cont, found := d.Get(models.NVD); found {
nvd = cont
}
summary := fmt.Sprintf("%s\n%s/%s\n%s\n%sConfidence: %v",
nvd.Summary,
cveDetailsBaseURL,
d.VulnInfo.CveID,
distroLinks(d, r.Family)[0].url,
packsVer,
d.VulnInfo.Confidence,
)
scols = []string{
d.VulnInfo.CveID,
fmt.Sprintf("%-4.1f (%s)",
d.CvssV2Score(),
"TODO",
),
summary,
}
default:
summary := fmt.Sprintf("%s\n%sConfidence: %v",
distroLinks(d, r.Family)[0].url, packsVer, d.VulnInfo.Confidence)
scols = []string{
d.VulnInfo.CveID,
"?",
summary,
}
}
// case 0 < d.CvssV2Score():
// var nvd *models.CveContent
// if cont, found := d.Get(models.NVD); found {
// nvd = cont
// }
// summary := fmt.Sprintf("%s\n%s/%s\n%s\n%sConfidence: %v",
// nvd.Summary,
// cveDetailsBaseURL,
// d.VulnInfo.CveID,
// distroLinks(d, r.Family)[0].url,
// packsVer,
// d.VulnInfo.Confidence,
// )
// scols = []string{
// d.VulnInfo.CveID,
// fmt.Sprintf("%-4.1f (%s)",
// d.CvssV2Score(),
// "TODO",
// ),
// summary,
// }
// default:
// summary := fmt.Sprintf("%s\n%sConfidence: %v",
// distroLinks(d, r.Family)[0].url, packsVer, d.VulnInfo.Confidence)
// scols = []string{
// d.VulnInfo.CveID,
// "?",
// summary,
// }
// }
cols := make([]interface{}, len(scols))
for i := range cols {
cols[i] = scols[i]
}
stable.AddRow(cols...)
stable.AddRow("")
}
// cols := make([]interface{}, len(scols))
// for i := range cols {
// cols[i] = scols[i]
// }
// stable.AddRow(cols...)
// stable.AddRow("")
// }
return fmt.Sprintf("%s\n%s\n", header, stable)
}
@@ -206,32 +207,34 @@ func formatFullPlainText(r models.ScanResult) string {
header, r.Errors)
}
if len(r.KnownCves) == 0 && len(r.UnknownCves) == 0 {
return fmt.Sprintf(`
%s
No CVE-IDs are found in updatable packages.
%s
`, header, r.Packages.FormatUpdatablePacksSummary())
}
//TODO
// if len(r.KnownCves) == 0 && len(r.UnknownCves) == 0 {
// return fmt.Sprintf(`
// %s
// No CVE-IDs are found in updatable packages.
// %s
// `, header, r.Packages.FormatUpdatablePacksSummary())
// }
scoredReport, unscoredReport := []string{}, []string{}
scoredReport, unscoredReport = formatPlainTextDetails(r, r.Family)
// scoredReport, unscoredReport := []string{}, []string{}
// scoredReport, unscoredReport = formatPlainTextDetails(r, r.Family)
unscored := ""
if !config.Conf.IgnoreUnscoredCves {
unscored = strings.Join(unscoredReport, "\n\n")
}
// unscored := ""
// if !config.Conf.IgnoreUnscoredCves {
// unscored = strings.Join(unscoredReport, "\n\n")
// }
scored := strings.Join(scoredReport, "\n\n")
detail := fmt.Sprintf(`
%s
// scored := strings.Join(scoredReport, "\n\n")
// detail := fmt.Sprintf(`
// %s
%s
`,
scored,
unscored,
)
return fmt.Sprintf("%s\n%s\n%s", header, detail, formatChangelogs(r))
// %s
// `,
// scored,
// unscored,
// )
// return fmt.Sprintf("%s\n%s\n%s", header, detail, formatChangelogs(r))
return ""
}
//TODO
@@ -266,116 +269,116 @@ func formatPlainTextDetails(r models.ScanResult, osFamily string) (scoredReport,
return
}
func formatPlainTextUnknownCve(cveInfo models.CveInfo, osFamily string) string {
cveID := cveInfo.VulnInfo.CveID
dtable := uitable.New()
dtable.MaxColWidth = maxColWidth
dtable.Wrap = true
dtable.AddRow(cveID)
dtable.AddRow("-------------")
dtable.AddRow("Score", "?")
dtable.AddRow("NVD", fmt.Sprintf("%s/%s", nvdBaseURL, cveID))
dlinks := distroLinks(cveInfo, osFamily)
for _, link := range dlinks {
dtable.AddRow(link.title, link.url)
}
dtable.AddRow("CVE Details", fmt.Sprintf("%s/%s", cveDetailsBaseURL, cveID))
dtable = addPackageInfos(dtable, cveInfo.Packages)
dtable = addCpeNames(dtable, cveInfo.CpeNames)
dtable.AddRow("Confidence", cveInfo.VulnInfo.Confidence)
// func formatPlainTextUnknownCve(cveInfo models.CveInfo, osFamily string) string {
// cveID := cveInfo.VulnInfo.CveID
// dtable := uitable.New()
// dtable.MaxColWidth = maxColWidth
// dtable.Wrap = true
// dtable.AddRow(cveID)
// dtable.AddRow("-------------")
// dtable.AddRow("Score", "?")
// dtable.AddRow("NVD", fmt.Sprintf("%s/%s", nvdBaseURL, cveID))
// dlinks := distroLinks(cveInfo, osFamily)
// for _, link := range dlinks {
// dtable.AddRow(link.title, link.url)
// }
// dtable.AddRow("CVE Details", fmt.Sprintf("%s/%s", cveDetailsBaseURL, cveID))
// dtable = addPackageInfos(dtable, cveInfo.Packages)
// dtable = addCpeNames(dtable, cveInfo.CpeNames)
// dtable.AddRow("Confidence", cveInfo.VulnInfo.Confidence)
return fmt.Sprintf("%s", dtable)
}
// return fmt.Sprintf("%s", dtable)
// }
//TODO
func formatPlainTextDetailsLangJa(cveInfo models.CveInfo, osFamily string) string {
return "TODO"
// cveDetail := cveInfo.CveDetail
// cveID := cveDetail.CveID
// jvn := cveDetail.Jvn
// func formatPlainTextDetailsLangJa(cveInfo models.CveInfo, osFamily string) string {
// return "TODO"
// cveDetail := cveInfo.CveDetail
// cveID := cveDetail.CveID
// jvn := cveDetail.Jvn
// dtable := uitable.New()
// dtable.MaxColWidth = maxColWidth
// dtable.Wrap = true
// dtable.AddRow(cveID)
// dtable.AddRow("-------------")
// if score := cveDetail.Jvn.CvssScore(); 0 < score {
// dtable.AddRow("Score",
// fmt.Sprintf("%4.1f (%s)",
// cveDetail.Jvn.CvssScore(),
// jvn.CvssSeverity(),
// ))
// } else {
// dtable.AddRow("Score", "?")
// }
// dtable.AddRow("Vector", jvn.CvssVector())
// dtable.AddRow("Title", jvn.CveTitle())
// dtable.AddRow("Description", jvn.CveSummary())
// dtable.AddRow(cveDetail.CweID(), cweURL(cveDetail.CweID()))
// dtable.AddRow(cveDetail.CweID()+"(JVN)", cweJvnURL(cveDetail.CweID()))
// dtable := uitable.New()
// dtable.MaxColWidth = maxColWidth
// dtable.Wrap = true
// dtable.AddRow(cveID)
// dtable.AddRow("-------------")
// if score := cveDetail.Jvn.CvssScore(); 0 < score {
// dtable.AddRow("Score",
// fmt.Sprintf("%4.1f (%s)",
// cveDetail.Jvn.CvssScore(),
// jvn.CvssSeverity(),
// ))
// } else {
// dtable.AddRow("Score", "?")
// }
// dtable.AddRow("Vector", jvn.CvssVector())
// dtable.AddRow("Title", jvn.CveTitle())
// dtable.AddRow("Description", jvn.CveSummary())
// dtable.AddRow(cveDetail.CweID(), cweURL(cveDetail.CweID()))
// dtable.AddRow(cveDetail.CweID()+"(JVN)", cweJvnURL(cveDetail.CweID()))
// dtable.AddRow("JVN", jvn.Link())
// dtable.AddRow("NVD", fmt.Sprintf("%s/%s", nvdBaseURL, cveID))
// dtable.AddRow("MITRE", fmt.Sprintf("%s%s", mitreBaseURL, cveID))
// dtable.AddRow("CVE Details", fmt.Sprintf("%s/%s", cveDetailsBaseURL, cveID))
// dtable.AddRow("CVSSv2 Clac", fmt.Sprintf(cvssV2CalcBaseURL, cveID))
// dtable.AddRow("CVSSv3 Clac", fmt.Sprintf(cvssV3CalcBaseURL, cveID))
// dtable.AddRow("JVN", jvn.Link())
// dtable.AddRow("NVD", fmt.Sprintf("%s/%s", nvdBaseURL, cveID))
// dtable.AddRow("MITRE", fmt.Sprintf("%s%s", mitreBaseURL, cveID))
// dtable.AddRow("CVE Details", fmt.Sprintf("%s/%s", cveDetailsBaseURL, cveID))
// dtable.AddRow("CVSSv2 Clac", fmt.Sprintf(cvssV2CalcBaseURL, cveID))
// dtable.AddRow("CVSSv3 Clac", fmt.Sprintf(cvssV3CalcBaseURL, cveID))
// dlinks := distroLinks(cveInfo, osFamily)
// for _, link := range dlinks {
// dtable.AddRow(link.title, link.url)
// }
// dlinks := distroLinks(cveInfo, osFamily)
// for _, link := range dlinks {
// dtable.AddRow(link.title, link.url)
// }
// dtable = addPackageInfos(dtable, cveInfo.Packages)
// dtable = addCpeNames(dtable, cveInfo.CpeNames)
// dtable.AddRow("Confidence", cveInfo.VulnInfo.Confidence)
// dtable = addPackageInfos(dtable, cveInfo.Packages)
// dtable = addCpeNames(dtable, cveInfo.CpeNames)
// dtable.AddRow("Confidence", cveInfo.VulnInfo.Confidence)
// return fmt.Sprintf("%s", dtable)
}
// return fmt.Sprintf("%s", dtable)
// }
//TODO
func formatPlainTextDetailsLangEn(d models.CveInfo, osFamily string) string {
return ""
// cveDetail := d.CveDetail
// cveID := cveDetail.CveID
// nvd := cveDetail.Nvd
// func formatPlainTextDetailsLangEn(d models.CveInfo, osFamily string) string {
// return ""
// cveDetail := d.CveDetail
// cveID := cveDetail.CveID
// nvd := cveDetail.Nvd
// dtable := uitable.New()
// dtable.MaxColWidth = maxColWidth
// dtable.Wrap = true
// dtable.AddRow(cveID)
// dtable.AddRow("-------------")
// dtable := uitable.New()
// dtable.MaxColWidth = maxColWidth
// dtable.Wrap = true
// dtable.AddRow(cveID)
// dtable.AddRow("-------------")
// if score := cveDetail.Nvd.CvssScore(); 0 < score {
// dtable.AddRow("Score",
// fmt.Sprintf("%4.1f (%s)",
// cveDetail.Nvd.CvssScore(),
// nvd.CvssSeverity(),
// ))
// } else {
// dtable.AddRow("Score", "?")
// }
// if score := cveDetail.Nvd.CvssScore(); 0 < score {
// dtable.AddRow("Score",
// fmt.Sprintf("%4.1f (%s)",
// cveDetail.Nvd.CvssScore(),
// nvd.CvssSeverity(),
// ))
// } else {
// dtable.AddRow("Score", "?")
// }
// dtable.AddRow("Vector", nvd.CvssVector())
// dtable.AddRow("Summary", nvd.CveSummary())
// dtable.AddRow("CWE", cweURL(cveDetail.CweID()))
// dtable.AddRow("Vector", nvd.CvssVector())
// dtable.AddRow("Summary", nvd.CveSummary())
// dtable.AddRow("CWE", cweURL(cveDetail.CweID()))
// dtable.AddRow("NVD", fmt.Sprintf("%s/%s", nvdBaseURL, cveID))
// dtable.AddRow("MITRE", fmt.Sprintf("%s%s", mitreBaseURL, cveID))
// dtable.AddRow("CVE Details", fmt.Sprintf("%s/%s", cveDetailsBaseURL, cveID))
// dtable.AddRow("CVSSv2 Clac", fmt.Sprintf(cvssV2CalcBaseURL, cveID))
// dtable.AddRow("CVSSv3 Clac", fmt.Sprintf(cvssV3CalcBaseURL, cveID))
// dtable.AddRow("NVD", fmt.Sprintf("%s/%s", nvdBaseURL, cveID))
// dtable.AddRow("MITRE", fmt.Sprintf("%s%s", mitreBaseURL, cveID))
// dtable.AddRow("CVE Details", fmt.Sprintf("%s/%s", cveDetailsBaseURL, cveID))
// dtable.AddRow("CVSSv2 Clac", fmt.Sprintf(cvssV2CalcBaseURL, cveID))
// dtable.AddRow("CVSSv3 Clac", fmt.Sprintf(cvssV3CalcBaseURL, cveID))
// links := distroLinks(d, osFamily)
// for _, link := range links {
// dtable.AddRow(link.title, link.url)
// }
// dtable = addPackageInfos(dtable, d.Packages)
// dtable = addCpeNames(dtable, d.CpeNames)
// dtable.AddRow("Confidence", d.VulnInfo.Confidence)
// links := distroLinks(d, osFamily)
// for _, link := range links {
// dtable.AddRow(link.title, link.url)
// }
// dtable = addPackageInfos(dtable, d.Packages)
// dtable = addCpeNames(dtable, d.CpeNames)
// dtable.AddRow("Confidence", d.VulnInfo.Confidence)
// return fmt.Sprintf("%s\n", dtable)
}
// return fmt.Sprintf("%s\n", dtable)
// }
type distroLink struct {
title string
@@ -383,84 +386,84 @@ type distroLink struct {
}
// distroLinks add Vendor URL of the CVE to table
func distroLinks(cveInfo models.CveInfo, osFamily string) []distroLink {
cveID := cveInfo.VulnInfo.CveID
switch osFamily {
case "rhel", "centos":
links := []distroLink{
{
"RHEL-CVE",
fmt.Sprintf("%s/%s", redhatSecurityBaseURL, cveID),
},
}
for _, advisory := range cveInfo.DistroAdvisories {
aidURL := strings.Replace(advisory.AdvisoryID, ":", "-", -1)
links = append(links, distroLink{
// "RHEL-errata",
advisory.AdvisoryID,
fmt.Sprintf(redhatRHSABaseBaseURL, aidURL),
})
}
return links
case "oraclelinux":
links := []distroLink{
{
"Oracle-CVE",
fmt.Sprintf(oracleSecurityBaseURL, cveID),
},
}
for _, advisory := range cveInfo.DistroAdvisories {
links = append(links, distroLink{
// "Oracle-ELSA"
advisory.AdvisoryID,
fmt.Sprintf(oracleELSABaseBaseURL, advisory.AdvisoryID),
})
}
return links
case "amazon":
links := []distroLink{
{
"RHEL-CVE",
fmt.Sprintf("%s/%s", redhatSecurityBaseURL, cveID),
},
}
for _, advisory := range cveInfo.DistroAdvisories {
links = append(links, distroLink{
// "Amazon-ALAS",
advisory.AdvisoryID,
fmt.Sprintf(amazonSecurityBaseURL, advisory.AdvisoryID),
})
}
return links
case "ubuntu":
return []distroLink{
{
"Ubuntu-CVE",
fmt.Sprintf("%s/%s", ubuntuSecurityBaseURL, cveID),
},
//TODO Ubuntu USN
}
case "debian":
return []distroLink{
{
"Debian-CVE",
fmt.Sprintf("%s/%s", debianTrackerBaseURL, cveID),
},
// TODO Debian dsa
}
case "FreeBSD":
links := []distroLink{}
for _, advisory := range cveInfo.DistroAdvisories {
links = append(links, distroLink{
"FreeBSD-VuXML",
fmt.Sprintf(freeBSDVuXMLBaseURL, advisory.AdvisoryID),
})
}
return links
default:
return []distroLink{}
}
}
// func distroLinks(cveInfo models.CveInfo, osFamily string) []distroLink {
// cveID := cveInfo.VulnInfo.CveID
// switch osFamily {
// case "rhel", "centos":
// links := []distroLink{
// {
// "RHEL-CVE",
// fmt.Sprintf("%s/%s", redhatSecurityBaseURL, cveID),
// },
// }
// for _, advisory := range cveInfo.DistroAdvisories {
// aidURL := strings.Replace(advisory.AdvisoryID, ":", "-", -1)
// links = append(links, distroLink{
// // "RHEL-errata",
// advisory.AdvisoryID,
// fmt.Sprintf(redhatRHSABaseBaseURL, aidURL),
// })
// }
// return links
// case "oraclelinux":
// links := []distroLink{
// {
// "Oracle-CVE",
// fmt.Sprintf(oracleSecurityBaseURL, cveID),
// },
// }
// for _, advisory := range cveInfo.DistroAdvisories {
// links = append(links, distroLink{
// // "Oracle-ELSA"
// advisory.AdvisoryID,
// fmt.Sprintf(oracleELSABaseBaseURL, advisory.AdvisoryID),
// })
// }
// return links
// case "amazon":
// links := []distroLink{
// {
// "RHEL-CVE",
// fmt.Sprintf("%s/%s", redhatSecurityBaseURL, cveID),
// },
// }
// for _, advisory := range cveInfo.DistroAdvisories {
// links = append(links, distroLink{
// // "Amazon-ALAS",
// advisory.AdvisoryID,
// fmt.Sprintf(amazonSecurityBaseURL, advisory.AdvisoryID),
// })
// }
// return links
// case "ubuntu":
// return []distroLink{
// {
// "Ubuntu-CVE",
// fmt.Sprintf("%s/%s", ubuntuSecurityBaseURL, cveID),
// },
// //TODO Ubuntu USN
// }
// case "debian":
// return []distroLink{
// {
// "Debian-CVE",
// fmt.Sprintf("%s/%s", debianTrackerBaseURL, cveID),
// },
// // TODO Debian dsa
// }
// case "FreeBSD":
// links := []distroLink{}
// for _, advisory := range cveInfo.DistroAdvisories {
// links = append(links, distroLink{
// "FreeBSD-VuXML",
// fmt.Sprintf(freeBSDVuXMLBaseURL, advisory.AdvisoryID),
// })
// }
// return links
// default:
// return []distroLink{}
// }
// }
// addPackageInfos add package information related the CVE to table
func addPackageInfos(table *uitable.Table, packs []models.PackageInfo) *uitable.Table {

View File

@@ -267,9 +267,11 @@ func (l base) isAwsInstanceID(str string) bool {
func (l *base) convertToModel() models.ScanResult {
for _, p := range l.VulnInfos {
//TODO
sort.Sort(models.PackageInfosByName(p.Packages))
}
sort.Sort(l.VulnInfos)
//TODO
// sort.Sort(l.VulnInfos)
ctype := l.ServerInfo.Containers.Type
if l.ServerInfo.Container.ContainerID != "" && ctype == "" {

View File

@@ -20,7 +20,6 @@ package util
import (
"fmt"
"net/url"
"strconv"
"strings"
"github.com/future-architect/vuls/config"
@@ -136,31 +135,3 @@ func Truncate(str string, length int) string {
}
return str
}
// ParseCvss2 divide CVSSv2 string into score and vector
// 5/AV:N/AC:L/Au:N/C:N/I:N/A:P
func ParseCvss2(scoreVector string) (score float64, vector string) {
var err error
ss := strings.Split(scoreVector, "/")
if 1 < len(ss) {
if score, err = strconv.ParseFloat(ss[0], 64); err != nil {
return 0, ""
}
return score, strings.Join(ss[1:len(ss)], "/")
}
return 0, ""
}
// ParseCvss3 divide CVSSv3 string into score and vector
// 5.6/CVSS:3.0/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:L
func ParseCvss3(scoreVector string) (score float64, vector string) {
var err error
ss := strings.Split(scoreVector, "/CVSS:3.0/")
if 1 < len(ss) {
if score, err = strconv.ParseFloat(ss[0], 64); err != nil {
return 0, ""
}
return score, strings.Join(ss[1:len(ss)], "/")
}
return 0, ""
}

View File

@@ -171,69 +171,3 @@ func TestTruncate(t *testing.T) {
}
}
}
func TestParseCvss2(t *testing.T) {
type out struct {
score float64
vector string
}
var tests = []struct {
in string
out out
}{
{
in: "5/AV:N/AC:L/Au:N/C:N/I:N/A:P",
out: out{
score: 5.0,
vector: "AV:N/AC:L/Au:N/C:N/I:N/A:P",
},
},
{
in: "",
out: out{
score: 0,
vector: "",
},
},
}
for _, tt := range tests {
s, v := ParseCvss2(tt.in)
if s != tt.out.score || v != tt.out.vector {
t.Errorf("\nexpected: %f, %s\n actual: %f, %s",
tt.out.score, tt.out.vector, s, v)
}
}
}
func TestParseCvss3(t *testing.T) {
type out struct {
score float64
vector string
}
var tests = []struct {
in string
out out
}{
{
in: "5.6/CVSS:3.0/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:L",
out: out{
score: 5.6,
vector: "AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:L",
},
},
{
in: "",
out: out{
score: 0,
vector: "",
},
},
}
for _, tt := range tests {
s, v := ParseCvss3(tt.in)
if s != tt.out.score || v != tt.out.vector {
t.Errorf("\nexpected: %f, %s\n actual: %f, %s",
tt.out.score, tt.out.vector, s, v)
}
}
}