Change models structure
This commit is contained in:
28
Gopkg.lock
generated
28
Gopkg.lock
generated
@@ -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"
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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":
|
||||
|
||||
515
models/models.go
515
models/models.go
@@ -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
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
135
oval/redhat.go
135
oval/redhat.go
@@ -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
69
oval/redhat_test.go
Normal 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
236
report/slack.go
236
report/slack.go
@@ -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, " ")
|
||||
// }
|
||||
|
||||
271
report/tui.go
271
report/tui.go
@@ -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
|
||||
}
|
||||
|
||||
547
report/util.go
547
report/util.go
@@ -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 {
|
||||
|
||||
@@ -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 == "" {
|
||||
|
||||
29
util/util.go
29
util/util.go
@@ -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, ""
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user