From d077c29716bf1ea67babddc6448c250f163bf256 Mon Sep 17 00:00:00 2001 From: Kota Kanbe Date: Mon, 13 Mar 2017 20:55:23 +0900 Subject: [PATCH] Fix scan confidence on Ubuntu/Debian/Raspbian #362 --- scan/debian.go | 86 ++++++++++++++++++++++++--------------------- scan/debian_test.go | 54 +++++++++++++--------------- 2 files changed, 71 insertions(+), 69 deletions(-) diff --git a/scan/debian.go b/scan/debian.go index 80b33b23..10bff021 100644 --- a/scan/debian.go +++ b/scan/debian.go @@ -544,38 +544,59 @@ func (o *debian) scanPackageCveIDs(pack models.PackageInfo) ([]DetectedCveID, er return cveIDs, nil } -func (o *debian) getCveIDsFromChangelog(changelog string, - packName string, versionOrLater string) ([]DetectedCveID, models.Changelog) { +// Debian Version Numbers +// https://readme.phys.ethz.ch/documentation/debian_version_numbers/ +func (o *debian) getCveIDsFromChangelog( + changelog, name, ver string) ([]DetectedCveID, models.Changelog) { - if cveIDs, relevantChangelog, err := o.parseChangelog(changelog, packName, versionOrLater); err == nil { - return cveIDs, relevantChangelog + if cveIDs, relevant, err := o.parseChangelog( + changelog, name, ver, models.ChangelogExactMatch); err == nil { + return cveIDs, relevant } - //TODO switch case ubuntu, debian - ver := strings.Split(versionOrLater, "ubuntu")[0] - if cveIDs, relevantChangelog, err := o.parseChangelog(changelog, packName, ver); err == nil { - return cveIDs, relevantChangelog - } + var verAfterColon string + var err error - splittedByColon := strings.Split(versionOrLater, ":") + splittedByColon := strings.Split(ver, ":") if 1 < len(splittedByColon) { - ver = splittedByColon[1] - } - cveIDs, relevantChangelog, err := o.parseChangelog(changelog, packName, ver) - if err == nil { - return cveIDs, relevantChangelog + verAfterColon = splittedByColon[1] + if cveIDs, relevant, err := o.parseChangelog( + changelog, name, verAfterColon, models.ChangelogLenientMatch); err == nil { + return cveIDs, relevant + } } - ver = strings.Split(ver, "ubuntu")[0] - if cveIDs, relevantChangelog, err := o.parseChangelog(changelog, packName, ver); err == nil { - return cveIDs, relevantChangelog + delim := []string{"+", "~", "build"} + switch o.Distro.Family { + case "ubuntu": + delim = append(delim, "ubuntu") + case "debian": + case "Raspbian": + } + + for _, d := range delim { + ss := strings.Split(ver, d) + if 1 < len(ss) { + if cveIDs, relevant, err := o.parseChangelog( + changelog, name, ss[0], models.ChangelogLenientMatch); err == nil { + return cveIDs, relevant + } + } + + ss = strings.Split(verAfterColon, d) + if 1 < len(ss) { + if cveIDs, relevant, err := o.parseChangelog( + changelog, name, ss[0], models.ChangelogLenientMatch); err == nil { + return cveIDs, relevant + } + } } // Only logging the error. o.log.Error(err) for i, p := range o.Packages { - if p.Name == packName { + if p.Name == name { o.Packages[i].Changelog = models.Changelog{ Contents: "", Method: models.FailedToFindVersionInChangelog, @@ -605,17 +626,10 @@ var cveRe = regexp.MustCompile(`(CVE-\d{4}-\d{4,})`) // Collect CVE-IDs included in the changelog. // The version which specified in argument(versionOrLater) is excluded. -func (o *debian) parseChangelog(changelog string, packName string, versionOrLater string) ([]DetectedCveID, models.Changelog, error) { - +func (o *debian) parseChangelog(changelog, name, ver string, confidence models.Confidence) ([]DetectedCveID, models.Changelog, error) { buf, cveIDs := []string{}, []string{} - stopRe := regexp.MustCompile(fmt.Sprintf(`\(%s\)`, regexp.QuoteMeta(versionOrLater))) + stopRe := regexp.MustCompile(fmt.Sprintf(`\(%s\)`, regexp.QuoteMeta(ver))) stopLineFound := false - lenientStopLineFound := false - versionOrLaterlenient := versionOrLater - if i := strings.IndexRune(versionOrLaterlenient, '+'); i >= 0 { - versionOrLaterlenient = versionOrLaterlenient[:i] - } - lenientRe := regexp.MustCompile(fmt.Sprintf(`\(%s\)`, regexp.QuoteMeta(versionOrLaterlenient))) lines := strings.Split(changelog, "\n") for _, line := range lines { buf = append(buf, line) @@ -623,38 +637,30 @@ func (o *debian) parseChangelog(changelog string, packName string, versionOrLate // o.log.Debugf("Found the stop line: %s", line) stopLineFound = true break - } else if matchl := lenientRe.MatchString(line); matchl { - lenientStopLineFound = true - break } else if matches := cveRe.FindAllString(line, -1); 0 < len(matches) { for _, m := range matches { cveIDs = util.AppendIfMissing(cveIDs, m) } } } - if !stopLineFound && !lenientStopLineFound { + if !stopLineFound { return nil, models.Changelog{ Contents: "", Method: models.FailedToFindVersionInChangelog, }, fmt.Errorf( "Failed to scan CVE IDs. The version is not in changelog. name: %s, version: %s", - packName, - versionOrLater, + name, + ver, ) } - confidence := models.ChangelogExactMatch - if lenientStopLineFound { - confidence = models.ChangelogLenientMatch - } - clog := models.Changelog{ Contents: strings.Join(buf, "\n"), Method: string(confidence.DetectionMethod), } for i, p := range o.Packages { - if p.Name == packName { + if p.Name == name { o.Packages[i].Changelog = clog } } diff --git a/scan/debian_test.go b/scan/debian_test.go index b011a2dc..f27597de 100644 --- a/scan/debian_test.go +++ b/scan/debian_test.go @@ -58,7 +58,7 @@ func TestParseScannedPackagesLineDebian(t *testing.T) { } -func TestGetCveIDParsingChangelog(t *testing.T) { +func TestGetCveIDsFromChangelog(t *testing.T) { var tests = []struct { in []string @@ -81,9 +81,9 @@ systemd (228-4) unstable; urgency=medium systemd (228-3) unstable; urgency=medium`, }, []DetectedCveID{ - {"CVE-2015-2325", models.ChangelogExactMatch}, - {"CVE-2015-2326", models.ChangelogExactMatch}, - {"CVE-2015-3210", models.ChangelogExactMatch}, + {"CVE-2015-2325", models.ChangelogLenientMatch}, + {"CVE-2015-2326", models.ChangelogLenientMatch}, + {"CVE-2015-3210", models.ChangelogLenientMatch}, }, models.Changelog{ Contents: `systemd (229-2) unstable; urgency=medium @@ -94,8 +94,7 @@ CVE-2015-2326: heap buffer overflow in pcre_compile2(). (Closes: #783285) CVE-2015-3210: heap buffer overflow in pcre_compile2() / systemd (228-5) unstable; urgency=medium systemd (228-4) unstable; urgency=medium`, - //TODO - Method: models.ChangelogExactMatchStr, + Method: models.ChangelogLenientMatchStr, }, }, { @@ -116,9 +115,9 @@ systemd (228-4) unstable; urgency=medium`, pcre3 (2:8.35-7) unstable; urgency=medium`, }, []DetectedCveID{ - {"CVE-2015-2325", models.ChangelogExactMatch}, - {"CVE-2015-2326", models.ChangelogExactMatch}, - {"CVE-2015-3210", models.ChangelogExactMatch}, + {"CVE-2015-2325", models.ChangelogLenientMatch}, + {"CVE-2015-2326", models.ChangelogLenientMatch}, + {"CVE-2015-3210", models.ChangelogLenientMatch}, }, models.Changelog{ Contents: `pcre3 (2:8.38-2) unstable; urgency=low @@ -131,8 +130,7 @@ systemd (228-4) unstable; urgency=medium`, CVE-2015-2326: heap buffer overflow in pcre_compile2(). (Closes: #783285) CVE-2015-3210: heap buffer overflow in pcre_compile2() / pcre3 (2:8.35-7.1) unstable; urgency=medium`, - //TODO - Method: models.ChangelogExactMatchStr, + Method: models.ChangelogLenientMatchStr, }, }, { @@ -172,7 +170,6 @@ systemd (228-4) unstable; urgency=medium`, CVE-2015-2326: heap buffer overflow in pcre_compile2(). (Closes: #783285) CVE-2015-3210: heap buffer overflow in pcre_compile2() / sysvinit (2.88dsf-59.2ubuntu3) xenial; urgency=medium`, - //TODO Method: models.ChangelogExactMatchStr, }, }, @@ -195,10 +192,10 @@ systemd (228-4) unstable; urgency=medium`, util-linux (2.27-3ubuntu1) xenial; urgency=medium`, }, []DetectedCveID{ - {"CVE-2015-2325", models.ChangelogExactMatch}, - {"CVE-2015-2326", models.ChangelogExactMatch}, - {"CVE-2015-3210", models.ChangelogExactMatch}, - {"CVE-2016-1000000", models.ChangelogExactMatch}, + {"CVE-2015-2325", models.ChangelogLenientMatch}, + {"CVE-2015-2326", models.ChangelogLenientMatch}, + {"CVE-2015-3210", models.ChangelogLenientMatch}, + {"CVE-2016-1000000", models.ChangelogLenientMatch}, }, models.Changelog{ Contents: `util-linux (2.27.1-3ubuntu1) xenial; urgency=medium @@ -209,8 +206,7 @@ systemd (228-4) unstable; urgency=medium`, util-linux (2.27.1-2) unstable; urgency=medium util-linux (2.27.1-1ubuntu4) xenial; urgency=medium util-linux (2.27.1-1ubuntu3) xenial; urgency=medium`, - //TODO - Method: models.ChangelogExactMatchStr, + Method: models.ChangelogLenientMatchStr, }, }, { @@ -232,10 +228,10 @@ systemd (228-4) unstable; urgency=medium`, util-linux (2.27-3) xenial; urgency=medium`, }, []DetectedCveID{ - {"CVE-2015-2325", models.ChangelogExactMatch}, - {"CVE-2015-2326", models.ChangelogExactMatch}, - {"CVE-2015-3210", models.ChangelogExactMatch}, - {"CVE-2016-1000000", models.ChangelogExactMatch}, + {"CVE-2015-2325", models.ChangelogLenientMatch}, + {"CVE-2015-2326", models.ChangelogLenientMatch}, + {"CVE-2015-3210", models.ChangelogLenientMatch}, + {"CVE-2016-1000000", models.ChangelogLenientMatch}, }, models.Changelog{ Contents: `util-linux (2.27.1-3ubuntu1) xenial; urgency=medium @@ -250,8 +246,7 @@ systemd (228-4) unstable; urgency=medium`, util-linux (2.27.1-1ubuntu1) xenial; urgency=medium util-linux (2.27.1-1) unstable; urgency=medium util-linux (2.27-3) xenial; urgency=medium`, - //TODO - Method: models.ChangelogExactMatchStr, + Method: models.ChangelogLenientMatchStr, }, }, { @@ -276,16 +271,17 @@ systemd (228-4) unstable; urgency=medium`, } d := newDebian(config.ServerInfo{}) - for _, tt := range tests { + d.Distro.Family = "ubuntu" + for i, tt := range tests { aCveIDs, aClog := d.getCveIDsFromChangelog(tt.in[2], tt.in[0], tt.in[1]) if len(aCveIDs) != len(tt.cveIDs) { - t.Errorf("Len of return array are'nt same. expected %#v, actual %#v", tt.cveIDs, aCveIDs) + t.Errorf("[%d] Len of return array are'nt same. expected %#v, actual %#v", i, tt.cveIDs, aCveIDs) t.Errorf(pp.Sprintf("%s", tt.in)) continue } - for i := range tt.cveIDs { - if !reflect.DeepEqual(tt.cveIDs[i], aCveIDs[i]) { - t.Errorf("expected %v, actual %v", tt.cveIDs[i], aCveIDs[i]) + for j := range tt.cveIDs { + if !reflect.DeepEqual(tt.cveIDs[j], aCveIDs[j]) { + t.Errorf("[%d] expected %v, actual %v", i, tt.cveIDs[j], aCveIDs[j]) } }