feat(report): Add NVD as a source for mitigations, primarySrc URL and Patch URL (#1097)

* feat(report): Add NVD as a src for mitigations.

* feat(report): display "Vendor Advisory" URL in NVD

* feat(report): display patch urls in report, tui
This commit is contained in:
Kota Kanbe
2020-12-24 08:37:10 +09:00
committed by GitHub
parent cfbf779f9b
commit fb1fbf8f95
12 changed files with 244 additions and 279 deletions

View File

@@ -184,6 +184,9 @@ func DetectPkgCves(dbclient DBClient, r *models.ScanResult) error {
}
// To keep backward compatibility
// Newer versions use ListenPortStats,
// but older versions of Vuls are set to ListenPorts.
// Set ListenPorts to ListenPortStats to allow newer Vuls to report old results.
for i, pkg := range r.Packages {
for j, proc := range pkg.AffectedProcs {
for _, ipPort := range proc.ListenPorts {
@@ -277,7 +280,7 @@ func FillCveInfo(dbclient DBClient, r *models.ScanResult) error {
return nil
}
// fillCvesWithNvdJvn fetches NVD, JVN from CVE Database
// fillCvesWithNvdJvn fills CVE detail with NVD, JVN
func fillCvesWithNvdJvn(driver cvedb.DB, r *models.ScanResult) error {
cveIDs := []string{}
for _, v := range r.ScannedCves {
@@ -289,7 +292,7 @@ func fillCvesWithNvdJvn(driver cvedb.DB, r *models.ScanResult) error {
return err
}
for _, d := range ds {
nvd, exploits := models.ConvertNvdJSONToModel(d.CveID, d.NvdJSON)
nvd, exploits, mitigations := models.ConvertNvdJSONToModel(d.CveID, d.NvdJSON)
jvn := models.ConvertJvnToModel(d.CveID, d.Jvn)
alerts := fillCertAlerts(&d)
@@ -305,6 +308,7 @@ func fillCvesWithNvdJvn(driver cvedb.DB, r *models.ScanResult) error {
}
vinfo.AlertDict = alerts
vinfo.Exploits = append(vinfo.Exploits, exploits...)
vinfo.Mitigations = append(vinfo.Mitigations, mitigations...)
r.ScannedCves[cveID] = vinfo
break
}

View File

@@ -277,9 +277,8 @@ func attachmentText(vinfo models.VulnInfo, osFamily string, cweDict map[string]m
} else {
if 0 < len(vinfo.DistroAdvisories) {
links := []string{}
for k, v := range vinfo.VendorLinks(osFamily) {
links = append(links, fmt.Sprintf("<%s|%s>",
v, k))
for _, v := range vinfo.CveContents.PrimarySrcURLs(config.Conf.Lang, osFamily, vinfo.CveID) {
links = append(links, fmt.Sprintf("<%s|%s>", v.Value, v.Type))
}
v := fmt.Sprintf("<%s|%s> %s (%s)",
@@ -303,9 +302,8 @@ func attachmentText(vinfo models.VulnInfo, osFamily string, cweDict map[string]m
}
mitigation := ""
if vinfo.Mitigations(osFamily)[0].Type != models.Unknown {
mitigation = fmt.Sprintf("\nMitigation:\n```%s```\n",
vinfo.Mitigations(osFamily)[0].Value)
for _, m := range vinfo.Mitigations {
mitigation = fmt.Sprintf("\nMitigation:\n<%s|%s>", m.URL, m.CveContentType)
}
return fmt.Sprintf("*%4.1f (%s)* %s %s\n%s\n```\n%s\n```%s\n%s\n",

View File

@@ -866,6 +866,7 @@ type dataForTmpl struct {
Metasploits []models.Metasploit
Summary string
Mitigation string
PatchURLs []string
Confidences models.Confidences
Cwes []models.CweDictEntry
Alerts []models.Alert
@@ -894,14 +895,8 @@ func detailLines() (string, error) {
vinfo := vinfos[currentVinfo]
links := []string{}
if strings.HasPrefix(vinfo.CveID, "CVE-") {
links = append(links, vinfo.CveContents.SourceLinks(
config.Conf.Lang, r.Family, vinfo.CveID)[0].Value,
vinfo.Cvss2CalcURL(),
vinfo.Cvss3CalcURL())
}
for _, url := range vinfo.VendorLinks(r.Family) {
links = append(links, url)
for _, r := range vinfo.CveContents.PrimarySrcURLs(config.Conf.Lang, r.Family, vinfo.CveID) {
links = append(links, r.Value)
}
refsMap := map[string]models.Reference{}
@@ -924,7 +919,20 @@ func detailLines() (string, error) {
}
summary := vinfo.Summaries(r.Lang, r.Family)[0]
mitigation := vinfo.Mitigations(r.Family)[0]
mitigations := []string{}
for _, m := range vinfo.Mitigations {
switch m.CveContentType {
case models.RedHatAPI, models.Microsoft:
mitigations = append(mitigations,
fmt.Sprintf("%s (%s)", m.Mitigation, m.CveContentType))
case models.Nvd:
mitigations = append(mitigations,
fmt.Sprintf("* %s (%s)", m.URL, m.CveContentType))
default:
util.Log.Errorf("Unknown CveContentType: %s", m)
}
}
table := uitable.New()
table.MaxColWidth = maxColWidth
@@ -962,7 +970,8 @@ func detailLines() (string, error) {
CveID: vinfo.CveID,
Cvsses: fmt.Sprintf("%s\n", table),
Summary: fmt.Sprintf("%s (%s)", summary.Value, summary.Type),
Mitigation: fmt.Sprintf("%s (%s)", mitigation.Value, mitigation.Type),
Mitigation: strings.Join(mitigations, "\n"),
PatchURLs: vinfo.CveContents.PatchURLs(),
Confidences: vinfo.Confidences,
Cwes: cwes,
Links: util.Distinct(links),
@@ -991,13 +1000,18 @@ Summary
Mitigation
-----------
{{.Mitigation }}
{{.Mitigation }}
Links
Primary Src
-----------
{{range $link := .Links -}}
* {{$link}}
{{end}}
Patch
-----------
{{range $url := .PatchURLs -}}
* {{$url}}
{{end}}
CWE
-----------
{{range .Cwes -}}

View File

@@ -217,38 +217,18 @@ No CVE-IDs are found in updatable packages.
data = append(data, []string{"Summary", vuln.Summaries(
config.Conf.Lang, r.Family)[0].Value})
mitigation := vuln.Mitigations(r.Family)[0]
if mitigation.Type != models.Unknown {
data = append(data, []string{"Mitigation", mitigation.Value})
for _, m := range vuln.Mitigations {
data = append(data, []string{"Mitigation", m.URL})
}
cweURLs, top10URLs := []string{}, []string{}
cweTop25URLs, sansTop25URLs := []string{}, []string{}
for _, v := range vuln.CveContents.UniqCweIDs(r.Family) {
name, url, top10Rank, top10URL, cweTop25Rank, cweTop25URL, sansTop25Rank, sansTop25URL := r.CweDict.Get(v.Value, r.Lang)
if top10Rank != "" {
data = append(data, []string{"CWE",
fmt.Sprintf("[OWASP Top%s] %s: %s (%s)",
top10Rank, v.Value, name, v.Type)})
top10URLs = append(top10URLs, top10URL)
}
if cweTop25Rank != "" {
data = append(data, []string{"CWE",
fmt.Sprintf("[CWE Top%s] %s: %s (%s)",
cweTop25Rank, v.Value, name, v.Type)})
cweTop25URLs = append(cweTop25URLs, cweTop25URL)
}
if sansTop25Rank != "" {
data = append(data, []string{"CWE",
fmt.Sprintf("[CWE/SANS Top%s] %s: %s (%s)",
sansTop25Rank, v.Value, name, v.Type)})
sansTop25URLs = append(sansTop25URLs, sansTop25URL)
}
if top10Rank == "" && cweTop25Rank == "" && sansTop25Rank == "" {
data = append(data, []string{"CWE", fmt.Sprintf("%s: %s (%s)",
v.Value, name, v.Type)})
}
cweURLs = append(cweURLs, url)
links := vuln.CveContents.PrimarySrcURLs(
config.Conf.Lang, r.Family, vuln.CveID)
for _, link := range links {
data = append(data, []string{"Primary Src", link.Value})
}
for _, url := range vuln.CveContents.PatchURLs() {
data = append(data, []string{"Patch", url})
}
vuln.AffectedPackages.Sort()
@@ -324,23 +304,35 @@ No CVE-IDs are found in updatable packages.
data = append(data, []string{"Confidence", confidence.String()})
}
if strings.HasPrefix(vuln.CveID, "CVE-") {
links := vuln.CveContents.SourceLinks(
config.Conf.Lang, r.Family, vuln.CveID)
data = append(data, []string{"Source", links[0].Value})
if 0 < len(vuln.Cvss2Scores(r.Family)) {
data = append(data, []string{"CVSSv2 Calc", vuln.Cvss2CalcURL()})
cweURLs, top10URLs := []string{}, []string{}
cweTop25URLs, sansTop25URLs := []string{}, []string{}
for _, v := range vuln.CveContents.UniqCweIDs(r.Family) {
name, url, top10Rank, top10URL, cweTop25Rank, cweTop25URL, sansTop25Rank, sansTop25URL := r.CweDict.Get(v.Value, r.Lang)
if top10Rank != "" {
data = append(data, []string{"CWE",
fmt.Sprintf("[OWASP Top%s] %s: %s (%s)",
top10Rank, v.Value, name, v.Type)})
top10URLs = append(top10URLs, top10URL)
}
if 0 < len(vuln.Cvss3Scores()) {
data = append(data, []string{"CVSSv3 Calc", vuln.Cvss3CalcURL()})
if cweTop25Rank != "" {
data = append(data, []string{"CWE",
fmt.Sprintf("[CWE Top%s] %s: %s (%s)",
cweTop25Rank, v.Value, name, v.Type)})
cweTop25URLs = append(cweTop25URLs, cweTop25URL)
}
if sansTop25Rank != "" {
data = append(data, []string{"CWE",
fmt.Sprintf("[CWE/SANS Top%s] %s: %s (%s)",
sansTop25Rank, v.Value, name, v.Type)})
sansTop25URLs = append(sansTop25URLs, sansTop25URL)
}
if top10Rank == "" && cweTop25Rank == "" && sansTop25Rank == "" {
data = append(data, []string{"CWE", fmt.Sprintf("%s: %s (%s)",
v.Value, name, v.Type)})
}
cweURLs = append(cweURLs, url)
}
vlinks := vuln.VendorLinks(r.Family)
for name, url := range vlinks {
data = append(data, []string{name, url})
}
for _, url := range cweURLs {
data = append(data, []string{"CWE", url})
}