Output changelog in report, TUI and JSON for Ubuntu/Debian/CentOS
This commit is contained in:
21
README.ja.md
21
README.ja.md
@@ -1022,6 +1022,27 @@ Confidence 100 / YumUpdateSecurityMatch
|
||||
| CpeNameMatch | 100 | All |Search for NVD information with CPE name specified in config.toml|
|
||||
|
||||
|
||||
### Changelog Part
|
||||
|
||||
The scan results of Ubuntu, Debian, Raspbian or CentOS are also output Changelog in TUI or report with -format-full-text.
|
||||
(RHEL, Amazon or FreeBSD will be available in the near future)
|
||||
|
||||
The output change log includes only the difference between the currently installed version and candidate version.
|
||||
|
||||
```
|
||||
tar-1.28-2.1 -> tar-1.28-2.1ubuntu0.1
|
||||
-------------------------------------
|
||||
tar (1.28-2.1ubuntu0.1) xenial-security; urgency=medium
|
||||
|
||||
* SECURITY UPDATE: extract pathname bypass
|
||||
- debian/patches/CVE-2016-6321.patch: skip members whose names contain
|
||||
".." in src/extract.c.
|
||||
- CVE-2016-6321
|
||||
|
||||
-- Marc Deslauriers <marc.deslauriers@ubuntu.com> Thu, 17 Nov 2016 11:06:07 -0500
|
||||
```
|
||||
|
||||
|
||||
## Example: Send scan results to Slack
|
||||
```
|
||||
$ vuls report \
|
||||
|
||||
21
README.md
21
README.md
@@ -1028,6 +1028,27 @@ Confidence 100 / YumUpdateSecurityMatch
|
||||
| PkgAuditMatch | 100 | FreeBSD |Detection using pkg audit|
|
||||
| CpeNameMatch | 100 | All |Search for NVD information with CPE name specified in config.toml|
|
||||
|
||||
|
||||
### Changelog Part
|
||||
|
||||
The scan results of Ubuntu, Debian, Raspbian or CentOS are also output Changelog in TUI or report with -format-full-text.
|
||||
(RHEL, Amazon or FreeBSD will be available in the near future)
|
||||
|
||||
The output change log includes only the difference between the currently installed version and candidate version.
|
||||
|
||||
```
|
||||
tar-1.28-2.1 -> tar-1.28-2.1ubuntu0.1
|
||||
-------------------------------------
|
||||
tar (1.28-2.1ubuntu0.1) xenial-security; urgency=medium
|
||||
|
||||
* SECURITY UPDATE: extract pathname bypass
|
||||
- debian/patches/CVE-2016-6321.patch: skip members whose names contain
|
||||
".." in src/extract.c.
|
||||
- CVE-2016-6321
|
||||
|
||||
-- Marc Deslauriers <marc.deslauriers@ubuntu.com> Thu, 17 Nov 2016 11:06:07 -0500
|
||||
```
|
||||
|
||||
## Example: Send scan results to Slack
|
||||
```
|
||||
$ vuls report \
|
||||
|
||||
@@ -250,20 +250,43 @@ func (c Confidence) String() string {
|
||||
return fmt.Sprintf("%d / %s", c.Score, c.DetectionMethod)
|
||||
}
|
||||
|
||||
const (
|
||||
// CpeNameMatchStr is a String representation of CpeNameMatch
|
||||
CpeNameMatchStr = "CpeNameMatch"
|
||||
|
||||
// YumUpdateSecurityMatchStr is a String representation of YumUpdateSecurityMatch
|
||||
YumUpdateSecurityMatchStr = "YumUpdateSecurityMatch"
|
||||
|
||||
// PkgAuditMatchStr is a String representation of PkgAuditMatch
|
||||
PkgAuditMatchStr = "PkgAuditMatch"
|
||||
|
||||
// ChangelogExactMatchStr is a String representation of ChangelogExactMatch
|
||||
ChangelogExactMatchStr = "ChangelogExactMatch"
|
||||
|
||||
// ChangelogLenientMatchStr is a String representation of ChangelogLenientMatch
|
||||
ChangelogLenientMatchStr = "ChangelogLenientMatch"
|
||||
|
||||
// FailedToGetChangelog is a String representation of FailedToGetChangelog
|
||||
FailedToGetChangelog = "FailedToGetChangelog"
|
||||
|
||||
// FailedToFindVersionInChangelog is a String representation of FailedToFindVersionInChangelog
|
||||
FailedToFindVersionInChangelog = "FailedToFindVersionInChangelog"
|
||||
)
|
||||
|
||||
// CpeNameMatch is a ranking how confident the CVE-ID was deteted correctly
|
||||
var CpeNameMatch = Confidence{100, "CpeNameMatch"}
|
||||
var CpeNameMatch = Confidence{100, CpeNameMatchStr}
|
||||
|
||||
// YumUpdateSecurityMatch is a ranking how confident the CVE-ID was deteted correctly
|
||||
var YumUpdateSecurityMatch = Confidence{100, "YumUpdateSecurityMatch"}
|
||||
var YumUpdateSecurityMatch = Confidence{100, YumUpdateSecurityMatchStr}
|
||||
|
||||
// PkgAuditMatch is a ranking how confident the CVE-ID was deteted correctly
|
||||
var PkgAuditMatch = Confidence{100, "PkgAuditMatch"}
|
||||
var PkgAuditMatch = Confidence{100, PkgAuditMatchStr}
|
||||
|
||||
// ChangelogExactMatch is a ranking how confident the CVE-ID was deteted correctly
|
||||
var ChangelogExactMatch = Confidence{95, "ChangelogExactMatch"}
|
||||
var ChangelogExactMatch = Confidence{95, ChangelogExactMatchStr}
|
||||
|
||||
// ChangelogLenientMatch is a ranking how confident the CVE-ID was deteted correctly
|
||||
var ChangelogLenientMatch = Confidence{50, "ChangelogLenientMatch"}
|
||||
var ChangelogLenientMatch = Confidence{50, ChangelogLenientMatchStr}
|
||||
|
||||
// VulnInfos is VulnInfo list, getter/setter, sortable methods.
|
||||
type VulnInfos []VulnInfo
|
||||
@@ -285,6 +308,9 @@ func (v *VulnInfo) NilSliceToEmpty() {
|
||||
if v.DistroAdvisories == nil {
|
||||
v.DistroAdvisories = []DistroAdvisory{}
|
||||
}
|
||||
if v.Packages == nil {
|
||||
v.Packages = PackageInfoList{}
|
||||
}
|
||||
}
|
||||
|
||||
// FindByCveID find by CVEID
|
||||
@@ -466,6 +492,14 @@ type PackageInfo struct {
|
||||
NewVersion string
|
||||
NewRelease string
|
||||
Repository string
|
||||
Changelog Changelog
|
||||
}
|
||||
|
||||
// Changelog has contents of changelog and how to get it.
|
||||
// Method: modesl.detectionMethodStr
|
||||
type Changelog struct {
|
||||
Contents string
|
||||
Method string
|
||||
}
|
||||
|
||||
// ToStringCurrentVersion returns package name-version-release
|
||||
|
||||
@@ -47,7 +47,7 @@ func (w AzureBlobWriter) Write(rs ...models.ScanResult) (err error) {
|
||||
if c.Conf.FormatOneLineText {
|
||||
timestr := rs[0].ScannedAt.Format(time.RFC3339)
|
||||
k := fmt.Sprintf(timestr + "/summary.txt")
|
||||
text := toOneLineSummary(rs...)
|
||||
text := formatOneLineSummary(rs...)
|
||||
b := []byte(text)
|
||||
if err := createBlockBlob(cli, k, b); err != nil {
|
||||
return err
|
||||
@@ -69,7 +69,7 @@ func (w AzureBlobWriter) Write(rs ...models.ScanResult) (err error) {
|
||||
|
||||
if c.Conf.FormatShortText {
|
||||
k := key + "_short.txt"
|
||||
b := []byte(toShortPlainText(r))
|
||||
b := []byte(formatShortPlainText(r))
|
||||
if err := createBlockBlob(cli, k, b); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -77,7 +77,7 @@ func (w AzureBlobWriter) Write(rs ...models.ScanResult) (err error) {
|
||||
|
||||
if c.Conf.FormatFullText {
|
||||
k := key + "_full.txt"
|
||||
b := []byte(toFullPlainText(r))
|
||||
b := []byte(formatFullPlainText(r))
|
||||
if err := createBlockBlob(cli, k, b); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ func (w EMailWriter) Write(rs ...models.ScanResult) (err error) {
|
||||
|
||||
for _, r := range rs {
|
||||
if conf.FormatOneEMail {
|
||||
message += toFullPlainText(r) + "\r\n\r\n"
|
||||
message += formatFullPlainText(r) + "\r\n\r\n"
|
||||
totalResult.KnownCves = append(totalResult.KnownCves, r.KnownCves...)
|
||||
totalResult.UnknownCves = append(totalResult.UnknownCves, r.UnknownCves...)
|
||||
} else {
|
||||
@@ -52,7 +52,7 @@ func (w EMailWriter) Write(rs ...models.ScanResult) (err error) {
|
||||
subject = fmt.Sprintf("%s%s %s",
|
||||
conf.EMail.SubjectPrefix, r.ServerInfo(), r.CveSummary())
|
||||
}
|
||||
message = toFullPlainText(r)
|
||||
message = formatFullPlainText(r)
|
||||
if err := sender.Send(subject, message); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -68,7 +68,7 @@ One Line Summary
|
||||
|
||||
|
||||
%s`,
|
||||
toOneLineSummary(rs...), message)
|
||||
formatOneLineSummary(rs...), message)
|
||||
|
||||
subject := fmt.Sprintf("%s %s",
|
||||
conf.EMail.SubjectPrefix,
|
||||
|
||||
@@ -38,7 +38,7 @@ type LocalFileWriter struct {
|
||||
func (w LocalFileWriter) Write(rs ...models.ScanResult) (err error) {
|
||||
if c.Conf.FormatOneLineText {
|
||||
path := filepath.Join(w.CurrentDir, "summary.txt")
|
||||
text := toOneLineSummary(rs...)
|
||||
text := formatOneLineSummary(rs...)
|
||||
if err := writeFile(path, []byte(text), 0600); err != nil {
|
||||
return fmt.Errorf(
|
||||
"Failed to write to file. path: %s, err: %s",
|
||||
@@ -63,7 +63,7 @@ func (w LocalFileWriter) Write(rs ...models.ScanResult) (err error) {
|
||||
if c.Conf.FormatShortText {
|
||||
p := path + "_short.txt"
|
||||
if err := writeFile(
|
||||
p, []byte(toShortPlainText(r)), 0600); err != nil {
|
||||
p, []byte(formatShortPlainText(r)), 0600); err != nil {
|
||||
return fmt.Errorf(
|
||||
"Failed to write text files. path: %s, err: %s", p, err)
|
||||
}
|
||||
@@ -72,7 +72,7 @@ func (w LocalFileWriter) Write(rs ...models.ScanResult) (err error) {
|
||||
if c.Conf.FormatFullText {
|
||||
p := path + "_full.txt"
|
||||
if err := writeFile(
|
||||
p, []byte(toFullPlainText(r)), 0600); err != nil {
|
||||
p, []byte(formatFullPlainText(r)), 0600); err != nil {
|
||||
return fmt.Errorf(
|
||||
"Failed to write text files. path: %s, err: %s", p, err)
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ func (w S3Writer) Write(rs ...models.ScanResult) (err error) {
|
||||
if c.Conf.FormatOneLineText {
|
||||
timestr := rs[0].ScannedAt.Format(time.RFC3339)
|
||||
k := fmt.Sprintf(timestr + "/summary.txt")
|
||||
text := toOneLineSummary(rs...)
|
||||
text := formatOneLineSummary(rs...)
|
||||
if err := putObject(svc, k, []byte(text)); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -76,7 +76,7 @@ func (w S3Writer) Write(rs ...models.ScanResult) (err error) {
|
||||
|
||||
if c.Conf.FormatShortText {
|
||||
k := key + "_short.txt"
|
||||
text := toShortPlainText(r)
|
||||
text := formatShortPlainText(r)
|
||||
if err := putObject(svc, k, []byte(text)); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -84,7 +84,7 @@ func (w S3Writer) Write(rs ...models.ScanResult) (err error) {
|
||||
|
||||
if c.Conf.FormatFullText {
|
||||
k := key + "_full.txt"
|
||||
text := toFullPlainText(r)
|
||||
text := formatFullPlainText(r)
|
||||
if err := putObject(svc, k, []byte(text)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ func (w StdoutWriter) WriteScanSummary(rs ...models.ScanResult) {
|
||||
fmt.Printf("\n\n")
|
||||
fmt.Println("One Line Summary")
|
||||
fmt.Println("================")
|
||||
fmt.Printf("%s\n", toScanSummary(rs...))
|
||||
fmt.Printf("%s\n", formatScanSummary(rs...))
|
||||
}
|
||||
|
||||
func (w StdoutWriter) Write(rs ...models.ScanResult) error {
|
||||
@@ -40,19 +40,19 @@ func (w StdoutWriter) Write(rs ...models.ScanResult) error {
|
||||
fmt.Print("\n\n")
|
||||
fmt.Println("One Line Summary")
|
||||
fmt.Println("================")
|
||||
fmt.Println(toOneLineSummary(rs...))
|
||||
fmt.Println(formatOneLineSummary(rs...))
|
||||
fmt.Print("\n")
|
||||
}
|
||||
|
||||
if c.Conf.FormatShortText {
|
||||
for _, r := range rs {
|
||||
fmt.Println(toShortPlainText(r))
|
||||
fmt.Println(formatShortPlainText(r))
|
||||
}
|
||||
}
|
||||
|
||||
if c.Conf.FormatFullText {
|
||||
for _, r := range rs {
|
||||
fmt.Println(toFullPlainText(r))
|
||||
fmt.Println(formatFullPlainText(r))
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
||||
101
report/tui.go
101
report/tui.go
@@ -133,6 +133,27 @@ func keybindings(g *gocui.Gui) (err error) {
|
||||
errs = append(errs, g.SetKeybinding("detail", gocui.KeyCtrlP, gocui.ModNone, previousSummary))
|
||||
errs = append(errs, g.SetKeybinding("detail", gocui.KeyEnter, gocui.ModNone, nextView))
|
||||
|
||||
// changelog
|
||||
errs = append(errs, g.SetKeybinding("changelog", gocui.KeyTab, gocui.ModNone, nextView))
|
||||
errs = append(errs, g.SetKeybinding("changelog", gocui.KeyCtrlQ, gocui.ModNone, previousView))
|
||||
errs = append(errs, g.SetKeybinding("changelog", gocui.KeyCtrlH, gocui.ModNone, nextView))
|
||||
// errs = append(errs, g.SetKeybinding("changelog", gocui.KeyCtrlL, gocui.ModNone, nextView))
|
||||
// errs = append(errs, g.SetKeybinding("changelog", gocui.KeyArrowUp, gocui.ModAlt, previousView))
|
||||
// errs = append(errs, g.SetKeybinding("changelog", gocui.KeyArrowLeft, gocui.ModAlt, nextView))
|
||||
errs = append(errs, g.SetKeybinding("changelog", gocui.KeyArrowDown, gocui.ModNone, cursorDown))
|
||||
errs = append(errs, g.SetKeybinding("changelog", gocui.KeyArrowUp, gocui.ModNone, cursorUp))
|
||||
errs = append(errs, g.SetKeybinding("changelog", gocui.KeyCtrlJ, gocui.ModNone, cursorDown))
|
||||
errs = append(errs, g.SetKeybinding("changelog", gocui.KeyCtrlK, gocui.ModNone, cursorUp))
|
||||
errs = append(errs, g.SetKeybinding("changelog", gocui.KeyCtrlD, gocui.ModNone, cursorPageDown))
|
||||
errs = append(errs, g.SetKeybinding("changelog", gocui.KeyCtrlU, gocui.ModNone, cursorPageUp))
|
||||
errs = append(errs, g.SetKeybinding("changelog", gocui.KeySpace, gocui.ModNone, cursorPageDown))
|
||||
errs = append(errs, g.SetKeybinding("changelog", gocui.KeyBackspace, gocui.ModNone, cursorPageUp))
|
||||
errs = append(errs, g.SetKeybinding("changelog", gocui.KeyBackspace2, gocui.ModNone, cursorPageUp))
|
||||
// errs = append(errs, g.SetKeybinding("changelog", gocui.KeyCtrlM, gocui.ModNone, cursorMoveMiddle))
|
||||
errs = append(errs, g.SetKeybinding("changelog", gocui.KeyCtrlN, gocui.ModNone, nextSummary))
|
||||
errs = append(errs, g.SetKeybinding("changelog", gocui.KeyCtrlP, gocui.ModNone, previousSummary))
|
||||
errs = append(errs, g.SetKeybinding("changelog", gocui.KeyEnter, gocui.ModNone, nextView))
|
||||
|
||||
// errs = append(errs, g.SetKeybinding("msg", gocui.KeyEnter, gocui.ModNone, delMsg))
|
||||
// errs = append(errs, g.SetKeybinding("detail", gocui.KeyEnter, gocui.ModNone, showMsg))
|
||||
|
||||
@@ -162,6 +183,8 @@ func nextView(g *gocui.Gui, v *gocui.View) error {
|
||||
case "summary":
|
||||
_, err = g.SetCurrentView("detail")
|
||||
case "detail":
|
||||
_, err = g.SetCurrentView("changelog")
|
||||
case "changelog":
|
||||
_, err = g.SetCurrentView("side")
|
||||
default:
|
||||
_, err = g.SetCurrentView("summary")
|
||||
@@ -182,6 +205,8 @@ func previousView(g *gocui.Gui, v *gocui.View) error {
|
||||
_, err = g.SetCurrentView("side")
|
||||
case "detail":
|
||||
_, err = g.SetCurrentView("summary")
|
||||
case "changelog":
|
||||
_, err = g.SetCurrentView("detail")
|
||||
default:
|
||||
_, err = g.SetCurrentView("side")
|
||||
}
|
||||
@@ -207,6 +232,11 @@ func movable(v *gocui.View, nextY int) (ok bool, yLimit int) {
|
||||
return false, currentDetailLimitY
|
||||
}
|
||||
return true, currentDetailLimitY
|
||||
case "changelog":
|
||||
if currentDetailLimitY < nextY {
|
||||
return false, currentDetailLimitY
|
||||
}
|
||||
return true, currentDetailLimitY
|
||||
default:
|
||||
return true, 0
|
||||
}
|
||||
@@ -217,7 +247,7 @@ func pageUpDownJumpCount(v *gocui.View) int {
|
||||
switch v.Name() {
|
||||
case "side", "summary":
|
||||
jump = 8
|
||||
case "detail":
|
||||
case "detail", "changelog":
|
||||
jump = 30
|
||||
default:
|
||||
jump = 8
|
||||
@@ -232,6 +262,9 @@ func onMovingCursorRedrawView(g *gocui.Gui, v *gocui.View) error {
|
||||
if err := redrawDetail(g); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := redrawChangelog(g); err != nil {
|
||||
return err
|
||||
}
|
||||
case "side":
|
||||
if err := changeHost(g, v); err != nil {
|
||||
return err
|
||||
@@ -395,6 +428,9 @@ func changeHost(g *gocui.Gui, v *gocui.View) error {
|
||||
if err := g.DeleteView("detail"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := g.DeleteView("changelog"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, cy := v.Cursor()
|
||||
l, err := v.Line(cy)
|
||||
@@ -416,6 +452,9 @@ func changeHost(g *gocui.Gui, v *gocui.View) error {
|
||||
if err := setDetailLayout(g); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := setChangelogLayout(g); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -430,6 +469,17 @@ func redrawDetail(g *gocui.Gui) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func redrawChangelog(g *gocui.Gui) error {
|
||||
if err := g.DeleteView("changelog"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := setChangelogLayout(g); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func getLine(g *gocui.Gui, v *gocui.View) error {
|
||||
var l string
|
||||
var err error
|
||||
@@ -498,12 +548,15 @@ func layout(g *gocui.Gui) error {
|
||||
if err := setDetailLayout(g); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := setChangelogLayout(g); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func setSideLayout(g *gocui.Gui) error {
|
||||
_, maxY := g.Size()
|
||||
if v, err := g.SetView("side", -1, -1, 40, maxY); err != nil {
|
||||
if v, err := g.SetView("side", -1, -1, 40, int(float64(maxY)*0.2)); err != nil {
|
||||
if err != gocui.ErrUnknownView {
|
||||
return err
|
||||
}
|
||||
@@ -614,14 +667,10 @@ func setDetailLayout(g *gocui.Gui) error {
|
||||
_, oy := summaryView.Origin()
|
||||
currentCveInfo = cy + oy
|
||||
|
||||
if v, err := g.SetView("detail", 40, int(float64(maxY)*0.2), maxX, maxY); err != nil {
|
||||
if v, err := g.SetView("detail", -1, int(float64(maxY)*0.2), int(float64(maxX)*0.5), maxY); err != nil {
|
||||
if err != gocui.ErrUnknownView {
|
||||
return err
|
||||
}
|
||||
// text := report.ToPlainTextDetailsLangEn(
|
||||
// currentScanResult.KnownCves[currentCveInfo],
|
||||
// currentScanResult.Family)
|
||||
|
||||
text, err := detailLines()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -635,6 +684,44 @@ func setDetailLayout(g *gocui.Gui) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func setChangelogLayout(g *gocui.Gui) error {
|
||||
maxX, maxY := g.Size()
|
||||
|
||||
summaryView, err := g.View("summary")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, cy := summaryView.Cursor()
|
||||
_, oy := summaryView.Origin()
|
||||
currentCveInfo = cy + oy
|
||||
|
||||
if v, err := g.SetView("changelog", int(float64(maxX)*0.5), int(float64(maxY)*0.2), maxX, maxY); err != nil {
|
||||
if err != gocui.ErrUnknownView {
|
||||
return err
|
||||
}
|
||||
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")
|
||||
}
|
||||
}
|
||||
}
|
||||
text := strings.Join(lines, "\n")
|
||||
fmt.Fprint(v, text)
|
||||
v.Editable = false
|
||||
v.Wrap = true
|
||||
|
||||
currentDetailLimitY = len(strings.Split(text, "\n")) - 1
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type dataForTmpl struct {
|
||||
CveID string
|
||||
CvssScore string
|
||||
|
||||
@@ -29,7 +29,7 @@ import (
|
||||
|
||||
const maxColWidth = 80
|
||||
|
||||
func toScanSummary(rs ...models.ScanResult) string {
|
||||
func formatScanSummary(rs ...models.ScanResult) string {
|
||||
table := uitable.New()
|
||||
table.MaxColWidth = maxColWidth
|
||||
table.Wrap = true
|
||||
@@ -55,7 +55,7 @@ func toScanSummary(rs ...models.ScanResult) string {
|
||||
return fmt.Sprintf("%s\n", table)
|
||||
}
|
||||
|
||||
func toOneLineSummary(rs ...models.ScanResult) string {
|
||||
func formatOneLineSummary(rs ...models.ScanResult) string {
|
||||
table := uitable.New()
|
||||
table.MaxColWidth = maxColWidth
|
||||
table.Wrap = true
|
||||
@@ -79,7 +79,7 @@ func toOneLineSummary(rs ...models.ScanResult) string {
|
||||
return fmt.Sprintf("%s\n", table)
|
||||
}
|
||||
|
||||
func toShortPlainText(r models.ScanResult) string {
|
||||
func formatShortPlainText(r models.ScanResult) string {
|
||||
stable := uitable.New()
|
||||
stable.MaxColWidth = maxColWidth
|
||||
stable.Wrap = true
|
||||
@@ -181,7 +181,7 @@ No CVE-IDs are found in updatable packages.
|
||||
return fmt.Sprintf("%s\n%s\n", header, stable)
|
||||
}
|
||||
|
||||
func toFullPlainText(r models.ScanResult) string {
|
||||
func formatFullPlainText(r models.ScanResult) string {
|
||||
serverInfo := r.ServerInfo()
|
||||
|
||||
var buf bytes.Buffer
|
||||
@@ -210,7 +210,7 @@ No CVE-IDs are found in updatable packages.
|
||||
}
|
||||
|
||||
scoredReport, unscoredReport := []string{}, []string{}
|
||||
scoredReport, unscoredReport = toPlainTextDetails(r, r.Family)
|
||||
scoredReport, unscoredReport = formatPlainTextDetails(r, r.Family)
|
||||
|
||||
unscored := ""
|
||||
if !config.Conf.IgnoreUnscoredCves {
|
||||
@@ -226,41 +226,41 @@ No CVE-IDs are found in updatable packages.
|
||||
scored,
|
||||
unscored,
|
||||
)
|
||||
return fmt.Sprintf("%s\n%s\n", header, detail)
|
||||
return fmt.Sprintf("%s\n%s\n%s", header, detail, formatChangelogs(r))
|
||||
}
|
||||
|
||||
func toPlainTextDetails(r models.ScanResult, osFamily string) (scoredReport, unscoredReport []string) {
|
||||
func formatPlainTextDetails(r models.ScanResult, osFamily string) (scoredReport, unscoredReport []string) {
|
||||
for _, cve := range r.KnownCves {
|
||||
switch config.Conf.Lang {
|
||||
case "en":
|
||||
if 0 < cve.CveDetail.Nvd.CvssScore() {
|
||||
scoredReport = append(
|
||||
scoredReport, toPlainTextDetailsLangEn(cve, osFamily))
|
||||
scoredReport, formatPlainTextDetailsLangEn(cve, osFamily))
|
||||
} else {
|
||||
scoredReport = append(
|
||||
scoredReport, toPlainTextUnknownCve(cve, osFamily))
|
||||
scoredReport, formatPlainTextUnknownCve(cve, osFamily))
|
||||
}
|
||||
case "ja":
|
||||
if 0 < cve.CveDetail.Jvn.CvssScore() {
|
||||
scoredReport = append(
|
||||
scoredReport, toPlainTextDetailsLangJa(cve, osFamily))
|
||||
scoredReport, formatPlainTextDetailsLangJa(cve, osFamily))
|
||||
} else if 0 < cve.CveDetail.Nvd.CvssScore() {
|
||||
scoredReport = append(
|
||||
scoredReport, toPlainTextDetailsLangEn(cve, osFamily))
|
||||
scoredReport, formatPlainTextDetailsLangEn(cve, osFamily))
|
||||
} else {
|
||||
scoredReport = append(
|
||||
scoredReport, toPlainTextUnknownCve(cve, osFamily))
|
||||
scoredReport, formatPlainTextUnknownCve(cve, osFamily))
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, cve := range r.UnknownCves {
|
||||
unscoredReport = append(
|
||||
unscoredReport, toPlainTextUnknownCve(cve, osFamily))
|
||||
unscoredReport, formatPlainTextUnknownCve(cve, osFamily))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func toPlainTextUnknownCve(cveInfo models.CveInfo, osFamily string) string {
|
||||
func formatPlainTextUnknownCve(cveInfo models.CveInfo, osFamily string) string {
|
||||
cveID := cveInfo.CveDetail.CveID
|
||||
dtable := uitable.New()
|
||||
dtable.MaxColWidth = maxColWidth
|
||||
@@ -284,7 +284,7 @@ func toPlainTextUnknownCve(cveInfo models.CveInfo, osFamily string) string {
|
||||
return fmt.Sprintf("%s", dtable)
|
||||
}
|
||||
|
||||
func toPlainTextDetailsLangJa(cveInfo models.CveInfo, osFamily string) string {
|
||||
func formatPlainTextDetailsLangJa(cveInfo models.CveInfo, osFamily string) string {
|
||||
cveDetail := cveInfo.CveDetail
|
||||
cveID := cveDetail.CveID
|
||||
jvn := cveDetail.Jvn
|
||||
@@ -327,7 +327,7 @@ func toPlainTextDetailsLangJa(cveInfo models.CveInfo, osFamily string) string {
|
||||
return fmt.Sprintf("%s", dtable)
|
||||
}
|
||||
|
||||
func toPlainTextDetailsLangEn(d models.CveInfo, osFamily string) string {
|
||||
func formatPlainTextDetailsLangEn(d models.CveInfo, osFamily string) string {
|
||||
cveDetail := d.CveDetail
|
||||
cveID := cveDetail.CveID
|
||||
nvd := cveDetail.Nvd
|
||||
@@ -467,3 +467,43 @@ func cweURL(cweID string) string {
|
||||
func cweJvnURL(cweID string) string {
|
||||
return fmt.Sprintf("http://jvndb.jvn.jp/ja/cwe/%s.html", cweID)
|
||||
}
|
||||
|
||||
func formatChangelogs(r models.ScanResult) string {
|
||||
buf := []string{}
|
||||
for _, p := range r.Packages {
|
||||
if p.NewVersion == "" {
|
||||
continue
|
||||
}
|
||||
clog := formatOneChangelog(p)
|
||||
buf = append(buf, clog, "\n\n")
|
||||
}
|
||||
return strings.Join(buf, "\n")
|
||||
}
|
||||
|
||||
func formatOneChangelog(p models.PackageInfo) string {
|
||||
buf := []string{}
|
||||
if p.NewVersion == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
packVer := fmt.Sprintf("%s -> %s",
|
||||
p.ToStringCurrentVersion(), p.ToStringNewVersion())
|
||||
var delim bytes.Buffer
|
||||
for i := 0; i < len(packVer); i++ {
|
||||
delim.WriteString("-")
|
||||
}
|
||||
|
||||
clog := p.Changelog.Contents
|
||||
if lines := strings.Split(clog, "\n"); len(lines) != 0 {
|
||||
clog = strings.Join(lines[0:len(lines)-1], "\n")
|
||||
}
|
||||
|
||||
switch p.Changelog.Method {
|
||||
case models.FailedToGetChangelog:
|
||||
clog = "No changelogs"
|
||||
case models.FailedToFindVersionInChangelog:
|
||||
clog = "Failed to parse changelogs. For detials, check yourself"
|
||||
}
|
||||
buf = append(buf, packVer, delim.String(), clog)
|
||||
return strings.Join(buf, "\n")
|
||||
}
|
||||
|
||||
102
scan/debian.go
102
scan/debian.go
@@ -311,7 +311,8 @@ func (o *debian) ensureChangelogCache(current cache.Meta) (*cache.Meta, error) {
|
||||
// Search from cache
|
||||
cached, found, err := cache.DB.GetMeta(current.Name)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to get meta. err: %s", err)
|
||||
return nil, fmt.Errorf(
|
||||
"Failed to get meta. Please remove cache.db and then try again. err: %s", err)
|
||||
}
|
||||
|
||||
if !found {
|
||||
@@ -447,7 +448,7 @@ func (o *debian) scanVulnInfos(upgradablePacks []models.PackageInfo, meta *cache
|
||||
func(p models.PackageInfo) {
|
||||
changelog := o.getChangelogCache(meta, p)
|
||||
if 0 < len(changelog) {
|
||||
cveIDs := o.getCveIDsFromChangelog(changelog, p.Name, p.Version)
|
||||
cveIDs, _ := o.getCveIDsFromChangelog(changelog, p.Name, p.Version)
|
||||
resChan <- struct {
|
||||
models.PackageInfo
|
||||
DetectedCveIDs
|
||||
@@ -549,9 +550,9 @@ func (o *debian) scanPackageCveIDs(pack models.PackageInfo) ([]DetectedCveID, er
|
||||
cmd := ""
|
||||
switch o.Distro.Family {
|
||||
case "ubuntu", "raspbian":
|
||||
cmd = fmt.Sprintf(`apt-get changelog %s | grep '\(urgency\|CVE\)'`, pack.Name)
|
||||
cmd = fmt.Sprintf(`PAGER=cat apt-get -q=2 changelog %s`, pack.Name)
|
||||
case "debian":
|
||||
cmd = fmt.Sprintf(`env PAGER=cat aptitude changelog %s | grep '\(urgency\|CVE\)'`, pack.Name)
|
||||
cmd = fmt.Sprintf(`PAGER=cat aptitude -q=2 changelog %s`, pack.Name)
|
||||
}
|
||||
cmd = util.PrependProxyEnv(cmd)
|
||||
|
||||
@@ -562,40 +563,65 @@ func (o *debian) scanPackageCveIDs(pack models.PackageInfo) ([]DetectedCveID, er
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if 0 < len(strings.TrimSpace(r.Stdout)) {
|
||||
err := cache.DB.PutChangelog(o.getServerInfo().GetServerName(), pack.Name, r.Stdout)
|
||||
stdout := strings.Replace(r.Stdout, "\r", "", -1)
|
||||
cveIDs, clog := o.getCveIDsFromChangelog(
|
||||
stdout, pack.Name, pack.Version)
|
||||
|
||||
if clog.Method != models.FailedToGetChangelog {
|
||||
err := cache.DB.PutChangelog(o.getServerInfo().GetServerName(), pack.Name, clog.Contents)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to put changelog into cache")
|
||||
}
|
||||
}
|
||||
|
||||
// No error will be returned. Only logging.
|
||||
return o.getCveIDsFromChangelog(r.Stdout, pack.Name, pack.Version), nil
|
||||
return cveIDs, nil
|
||||
}
|
||||
|
||||
func (o *debian) getCveIDsFromChangelog(changelog string,
|
||||
packName string, versionOrLater string) []DetectedCveID {
|
||||
packName string, versionOrLater string) ([]DetectedCveID, models.Changelog) {
|
||||
|
||||
if cveIDs, err := o.parseChangelog(changelog, packName, versionOrLater); err == nil {
|
||||
return cveIDs
|
||||
if cveIDs, relevantChangelog, err := o.parseChangelog(changelog, packName, versionOrLater); err == nil {
|
||||
return cveIDs, relevantChangelog
|
||||
}
|
||||
|
||||
//TODO switch case ubuntu, debian
|
||||
ver := strings.Split(versionOrLater, "ubuntu")[0]
|
||||
if cveIDs, err := o.parseChangelog(changelog, packName, ver); err == nil {
|
||||
return cveIDs
|
||||
if cveIDs, relevantChangelog, err := o.parseChangelog(changelog, packName, ver); err == nil {
|
||||
return cveIDs, relevantChangelog
|
||||
}
|
||||
|
||||
splittedByColon := strings.Split(versionOrLater, ":")
|
||||
if 1 < len(splittedByColon) {
|
||||
ver = splittedByColon[1]
|
||||
}
|
||||
cveIDs, err := o.parseChangelog(changelog, packName, ver)
|
||||
cveIDs, relevantChangelog, err := o.parseChangelog(changelog, packName, ver)
|
||||
if err == nil {
|
||||
return cveIDs
|
||||
return cveIDs, relevantChangelog
|
||||
}
|
||||
|
||||
ver = strings.Split(ver, "ubuntu")[0]
|
||||
if cveIDs, relevantChangelog, err := o.parseChangelog(changelog, packName, ver); err == nil {
|
||||
return cveIDs, relevantChangelog
|
||||
}
|
||||
|
||||
// Only logging the error.
|
||||
o.log.Error(err)
|
||||
return []DetectedCveID{}
|
||||
|
||||
for i, p := range o.Packages {
|
||||
if p.Name == packName {
|
||||
o.Packages[i].Changelog = models.Changelog{
|
||||
Contents: "",
|
||||
Method: models.FailedToFindVersionInChangelog,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If the version is not in changelog, return entire changelog to put into cache
|
||||
return []DetectedCveID{}, models.Changelog{
|
||||
Contents: changelog,
|
||||
Method: models.FailedToFindVersionInChangelog,
|
||||
}
|
||||
}
|
||||
|
||||
// DetectedCveID has CveID, Confidence and DetectionMethod fields
|
||||
@@ -609,13 +635,13 @@ type DetectedCveID struct {
|
||||
// DetectedCveIDs is a slice of DetectedCveID
|
||||
type DetectedCveIDs []DetectedCveID
|
||||
|
||||
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) (cves []DetectedCveID, err error) {
|
||||
func (o *debian) parseChangelog(changelog string, packName string, versionOrLater string) ([]DetectedCveID, models.Changelog, error) {
|
||||
|
||||
cveIDs := []string{}
|
||||
cveRe := regexp.MustCompile(`(CVE-\d{4}-\d{4,})`)
|
||||
buf, cveIDs := []string{}, []string{}
|
||||
stopRe := regexp.MustCompile(fmt.Sprintf(`\(%s\)`, regexp.QuoteMeta(versionOrLater)))
|
||||
stopLineFound := false
|
||||
lenientStopLineFound := false
|
||||
@@ -626,6 +652,7 @@ func (o *debian) parseChangelog(changelog string,
|
||||
lenientRe := regexp.MustCompile(fmt.Sprintf(`\(%s\)`, regexp.QuoteMeta(versionOrLaterlenient)))
|
||||
lines := strings.Split(changelog, "\n")
|
||||
for _, line := range lines {
|
||||
buf = append(buf, line)
|
||||
if match := stopRe.MatchString(line); match {
|
||||
// o.log.Debugf("Found the stop line: %s", line)
|
||||
stopLineFound = true
|
||||
@@ -640,21 +667,38 @@ func (o *debian) parseChangelog(changelog string,
|
||||
}
|
||||
}
|
||||
if !stopLineFound && !lenientStopLineFound {
|
||||
return cves, fmt.Errorf(
|
||||
"Failed to scan CVE IDs. The version is not in changelog. name: %s, version: %s",
|
||||
packName,
|
||||
versionOrLater,
|
||||
)
|
||||
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,
|
||||
)
|
||||
}
|
||||
|
||||
for _, id := range cveIDs {
|
||||
confidence := models.ChangelogExactMatch
|
||||
if lenientStopLineFound {
|
||||
confidence = models.ChangelogLenientMatch
|
||||
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 {
|
||||
o.Packages[i].Changelog = clog
|
||||
}
|
||||
}
|
||||
|
||||
cves := []DetectedCveID{}
|
||||
for _, id := range cveIDs {
|
||||
cves = append(cves, DetectedCveID{id, confidence})
|
||||
}
|
||||
return
|
||||
|
||||
return cves, clog, nil
|
||||
}
|
||||
|
||||
func (o *debian) splitAptCachePolicy(stdout string) map[string]string {
|
||||
|
||||
@@ -61,8 +61,9 @@ func TestParseScannedPackagesLineDebian(t *testing.T) {
|
||||
func TestGetCveIDParsingChangelog(t *testing.T) {
|
||||
|
||||
var tests = []struct {
|
||||
in []string
|
||||
expected []DetectedCveID
|
||||
in []string
|
||||
cveIDs []DetectedCveID
|
||||
changelog models.Changelog
|
||||
}{
|
||||
{
|
||||
// verubuntu1
|
||||
@@ -77,18 +78,25 @@ 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
|
||||
systemd (228-3) unstable; urgency=medium
|
||||
systemd (228-2) unstable; urgency=medium
|
||||
systemd (228-1) unstable; urgency=medium
|
||||
systemd (227-3) unstable; urgency=medium
|
||||
systemd (227-2) unstable; urgency=medium
|
||||
systemd (227-1) 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},
|
||||
},
|
||||
models.Changelog{
|
||||
Contents: `systemd (229-2) unstable; urgency=medium
|
||||
systemd (229-1) unstable; urgency=medium
|
||||
systemd (228-6) unstable; urgency=medium
|
||||
CVE-2015-2325: heap buffer overflow in compile_branch(). (Closes: #781795)
|
||||
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,
|
||||
},
|
||||
},
|
||||
{
|
||||
// ver
|
||||
@@ -96,22 +104,36 @@ systemd (227-1) unstable; urgency=medium`,
|
||||
"libpcre3",
|
||||
"2:8.35-7.1ubuntu1",
|
||||
`pcre3 (2:8.38-2) unstable; urgency=low
|
||||
pcre3 (2:8.38-1) unstable; urgency=low
|
||||
pcre3 (2:8.35-8) unstable; urgency=low
|
||||
pcre3 (2:8.35-7.4) unstable; urgency=medium
|
||||
pcre3 (2:8.35-7.3) unstable; urgency=medium
|
||||
pcre3 (2:8.35-7.2) unstable; urgency=low
|
||||
CVE-2015-2325: heap buffer overflow in compile_branch(). (Closes: #781795)
|
||||
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
|
||||
pcre3 (2:8.35-7) unstable; urgency=medium`,
|
||||
pcre3 (2:8.38-1) unstable; urgency=low
|
||||
pcre3 (2:8.35-8) unstable; urgency=low
|
||||
pcre3 (2:8.35-7.4) unstable; urgency=medium
|
||||
pcre3 (2:8.35-7.3) unstable; urgency=medium
|
||||
pcre3 (2:8.35-7.2) unstable; urgency=low
|
||||
CVE-2015-2325: heap buffer overflow in compile_branch(). (Closes: #781795)
|
||||
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
|
||||
pcre3 (2:8.35-7) unstable; urgency=medium`,
|
||||
},
|
||||
[]DetectedCveID{
|
||||
{"CVE-2015-2325", models.ChangelogExactMatch},
|
||||
{"CVE-2015-2326", models.ChangelogExactMatch},
|
||||
{"CVE-2015-3210", models.ChangelogExactMatch},
|
||||
},
|
||||
models.Changelog{
|
||||
Contents: `pcre3 (2:8.38-2) unstable; urgency=low
|
||||
pcre3 (2:8.38-1) unstable; urgency=low
|
||||
pcre3 (2:8.35-8) unstable; urgency=low
|
||||
pcre3 (2:8.35-7.4) unstable; urgency=medium
|
||||
pcre3 (2:8.35-7.3) unstable; urgency=medium
|
||||
pcre3 (2:8.35-7.2) unstable; urgency=low
|
||||
CVE-2015-2325: heap buffer overflow in compile_branch(). (Closes: #781795)
|
||||
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,
|
||||
},
|
||||
},
|
||||
{
|
||||
// ver-ubuntu3
|
||||
@@ -119,62 +141,58 @@ pcre3 (2:8.35-7) unstable; urgency=medium`,
|
||||
"sysvinit",
|
||||
"2.88dsf-59.2ubuntu3",
|
||||
`sysvinit (2.88dsf-59.3ubuntu1) xenial; urgency=low
|
||||
sysvinit (2.88dsf-59.3) unstable; urgency=medium
|
||||
CVE-2015-2325: heap buffer overflow in compile_branch(). (Closes: #781795)
|
||||
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
|
||||
sysvinit (2.88dsf-59.2ubuntu2) wily; urgency=medium
|
||||
sysvinit (2.88dsf-59.2ubuntu1) wily; urgency=medium
|
||||
CVE-2015-2321: heap buffer overflow in pcre_compile2(). (Closes: #783285)
|
||||
sysvinit (2.88dsf-59.2) unstable; urgency=medium
|
||||
sysvinit (2.88dsf-59.1ubuntu3) wily; urgency=medium
|
||||
CVE-2015-2322: heap buffer overflow in pcre_compile2(). (Closes: #783285)
|
||||
sysvinit (2.88dsf-59.1ubuntu2) wily; urgency=medium
|
||||
sysvinit (2.88dsf-59.1ubuntu1) wily; urgency=medium
|
||||
sysvinit (2.88dsf-59.1) unstable; urgency=medium
|
||||
CVE-2015-2326: heap buffer overflow in pcre_compile2(). (Closes: #783285)
|
||||
sysvinit (2.88dsf-59) unstable; urgency=medium
|
||||
sysvinit (2.88dsf-58) unstable; urgency=low
|
||||
sysvinit (2.88dsf-57) unstable; urgency=low`,
|
||||
sysvinit (2.88dsf-59.3) unstable; urgency=medium
|
||||
CVE-2015-2325: heap buffer overflow in compile_branch(). (Closes: #781795)
|
||||
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
|
||||
sysvinit (2.88dsf-59.2ubuntu2) wily; urgency=medium
|
||||
sysvinit (2.88dsf-59.2ubuntu1) wily; urgency=medium
|
||||
CVE-2015-2321: heap buffer overflow in pcre_compile2(). (Closes: #783285)
|
||||
sysvinit (2.88dsf-59.2) unstable; urgency=medium
|
||||
sysvinit (2.88dsf-59.1ubuntu3) wily; urgency=medium
|
||||
CVE-2015-2322: heap buffer overflow in pcre_compile2(). (Closes: #783285)
|
||||
sysvinit (2.88dsf-59.1ubuntu2) wily; urgency=medium
|
||||
sysvinit (2.88dsf-59.1ubuntu1) wily; urgency=medium
|
||||
sysvinit (2.88dsf-59.1) unstable; urgency=medium
|
||||
CVE-2015-2326: heap buffer overflow in pcre_compile2(). (Closes: #783285)
|
||||
sysvinit (2.88dsf-59) unstable; urgency=medium
|
||||
sysvinit (2.88dsf-58) unstable; urgency=low
|
||||
sysvinit (2.88dsf-57) unstable; urgency=low`,
|
||||
},
|
||||
[]DetectedCveID{
|
||||
{"CVE-2015-2325", models.ChangelogExactMatch},
|
||||
{"CVE-2015-2326", models.ChangelogExactMatch},
|
||||
{"CVE-2015-3210", models.ChangelogExactMatch},
|
||||
},
|
||||
models.Changelog{
|
||||
Contents: `sysvinit (2.88dsf-59.3ubuntu1) xenial; urgency=low
|
||||
sysvinit (2.88dsf-59.3) unstable; urgency=medium
|
||||
CVE-2015-2325: heap buffer overflow in compile_branch(). (Closes: #781795)
|
||||
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,
|
||||
},
|
||||
},
|
||||
{
|
||||
// 1:ver-ubuntu3
|
||||
[]string{
|
||||
"bsdutils",
|
||||
"1:2.27.1-1ubuntu3",
|
||||
` util-linux (2.27.1-3ubuntu1) xenial; urgency=medium
|
||||
util-linux (2.27.1-3) unstable; urgency=medium
|
||||
CVE-2015-2325: heap buffer overflow in compile_branch(). (Closes: #781795)
|
||||
CVE-2015-2326: heap buffer overflow in pcre_compile2(). (Closes: #783285)
|
||||
CVE-2015-3210: CVE-2016-1000000heap buffer overflow in pcre_compile2() /
|
||||
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
|
||||
util-linux (2.27.1-1ubuntu2) xenial; urgency=medium
|
||||
util-linux (2.27.1-1ubuntu1) xenial; urgency=medium
|
||||
util-linux (2.27.1-1) unstable; urgency=medium
|
||||
util-linux (2.27-3ubuntu1) xenial; urgency=medium
|
||||
util-linux (2.27-3) unstable; urgency=medium
|
||||
util-linux (2.27-2) unstable; urgency=medium
|
||||
util-linux (2.27-1) unstable; urgency=medium
|
||||
util-linux (2.27~rc2-2) experimental; urgency=medium
|
||||
util-linux (2.27~rc2-1) experimental; urgency=medium
|
||||
util-linux (2.27~rc1-1) experimental; urgency=medium
|
||||
util-linux (2.26.2-9) unstable; urgency=medium
|
||||
util-linux (2.26.2-8) experimental; urgency=medium
|
||||
util-linux (2.26.2-7) experimental; urgency=medium
|
||||
util-linux (2.26.2-6ubuntu3) wily; urgency=medium
|
||||
CVE-2015-2329: heap buffer overflow in compile_branch(). (Closes: #781795)
|
||||
util-linux (2.26.2-6ubuntu2) wily; urgency=medium
|
||||
util-linux (2.26.2-6ubuntu1) wily; urgency=medium
|
||||
util-linux (2.26.2-6) unstable; urgency=medium`,
|
||||
`util-linux (2.27.1-3ubuntu1) xenial; urgency=medium
|
||||
util-linux (2.27.1-3) unstable; urgency=medium
|
||||
CVE-2015-2325: heap buffer overflow in compile_branch(). (Closes: #781795)
|
||||
CVE-2015-2326: heap buffer overflow in pcre_compile2(). (Closes: #783285)
|
||||
CVE-2015-3210: CVE-2016-1000000heap buffer overflow in pcre_compile2() /
|
||||
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
|
||||
util-linux (2.27.1-1ubuntu2) xenial; urgency=medium
|
||||
util-linux (2.27.1-1ubuntu1) xenial; urgency=medium
|
||||
util-linux (2.27.1-1) unstable; urgency=medium
|
||||
util-linux (2.27-3ubuntu1) xenial; urgency=medium`,
|
||||
},
|
||||
[]DetectedCveID{
|
||||
{"CVE-2015-2325", models.ChangelogExactMatch},
|
||||
@@ -182,6 +200,59 @@ util-linux (2.26.2-6) unstable; urgency=medium`,
|
||||
{"CVE-2015-3210", models.ChangelogExactMatch},
|
||||
{"CVE-2016-1000000", models.ChangelogExactMatch},
|
||||
},
|
||||
models.Changelog{
|
||||
Contents: `util-linux (2.27.1-3ubuntu1) xenial; urgency=medium
|
||||
util-linux (2.27.1-3) unstable; urgency=medium
|
||||
CVE-2015-2325: heap buffer overflow in compile_branch(). (Closes: #781795)
|
||||
CVE-2015-2326: heap buffer overflow in pcre_compile2(). (Closes: #783285)
|
||||
CVE-2015-3210: CVE-2016-1000000heap buffer overflow in pcre_compile2() /
|
||||
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,
|
||||
},
|
||||
},
|
||||
{
|
||||
// 1:ver-ubuntu3
|
||||
[]string{
|
||||
"bsdutils",
|
||||
"1:2.27-3ubuntu3",
|
||||
`util-linux (2.27.1-3ubuntu1) xenial; urgency=medium
|
||||
util-linux (2.27.1-3) unstable; urgency=medium
|
||||
CVE-2015-2325: heap buffer overflow in compile_branch(). (Closes: #781795)
|
||||
CVE-2015-2326: heap buffer overflow in pcre_compile2(). (Closes: #783285)
|
||||
CVE-2015-3210: CVE-2016-1000000heap buffer overflow in pcre_compile2() /
|
||||
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
|
||||
util-linux (2.27.1-1ubuntu2) xenial; 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`,
|
||||
},
|
||||
[]DetectedCveID{
|
||||
{"CVE-2015-2325", models.ChangelogExactMatch},
|
||||
{"CVE-2015-2326", models.ChangelogExactMatch},
|
||||
{"CVE-2015-3210", models.ChangelogExactMatch},
|
||||
{"CVE-2016-1000000", models.ChangelogExactMatch},
|
||||
},
|
||||
models.Changelog{
|
||||
Contents: `util-linux (2.27.1-3ubuntu1) xenial; urgency=medium
|
||||
util-linux (2.27.1-3) unstable; urgency=medium
|
||||
CVE-2015-2325: heap buffer overflow in compile_branch(). (Closes: #781795)
|
||||
CVE-2015-2326: heap buffer overflow in pcre_compile2(). (Closes: #783285)
|
||||
CVE-2015-3210: CVE-2016-1000000heap buffer overflow in pcre_compile2() /
|
||||
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
|
||||
util-linux (2.27.1-1ubuntu2) xenial; 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,
|
||||
},
|
||||
},
|
||||
{
|
||||
// https://github.com/future-architect/vuls/pull/350
|
||||
@@ -189,28 +260,42 @@ util-linux (2.26.2-6) unstable; urgency=medium`,
|
||||
"tar",
|
||||
"1.27.1-2+b1",
|
||||
`tar (1.27.1-2+deb8u1) jessie-security; urgency=high
|
||||
* CVE-2016-6321: Bypassing the extract path name.
|
||||
tar (1.27.1-2) unstable; urgency=low`,
|
||||
* CVE-2016-6321: Bypassing the extract path name.
|
||||
tar (1.27.1-2) unstable; urgency=low`,
|
||||
},
|
||||
[]DetectedCveID{
|
||||
{"CVE-2016-6321", models.ChangelogLenientMatch},
|
||||
},
|
||||
models.Changelog{
|
||||
Contents: `tar (1.27.1-2+deb8u1) jessie-security; urgency=high
|
||||
* CVE-2016-6321: Bypassing the extract path name.
|
||||
tar (1.27.1-2) unstable; urgency=low`,
|
||||
Method: models.ChangelogLenientMatchStr,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
d := newDebian(config.ServerInfo{})
|
||||
for _, tt := range tests {
|
||||
actual := d.getCveIDsFromChangelog(tt.in[2], tt.in[0], tt.in[1])
|
||||
if len(actual) != len(tt.expected) {
|
||||
t.Errorf("Len of return array are'nt same. expected %#v, actual %#v", tt.expected, actual)
|
||||
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(pp.Sprintf("%s", tt.in))
|
||||
continue
|
||||
}
|
||||
for i := range tt.expected {
|
||||
if !reflect.DeepEqual(tt.expected[i], actual[i]) {
|
||||
t.Errorf("expected %v, actual %v", tt.expected[i], actual[i])
|
||||
for i := range tt.cveIDs {
|
||||
if !reflect.DeepEqual(tt.cveIDs[i], aCveIDs[i]) {
|
||||
t.Errorf("expected %v, actual %v", tt.cveIDs[i], aCveIDs[i])
|
||||
}
|
||||
}
|
||||
|
||||
if aClog.Contents != tt.changelog.Contents {
|
||||
t.Errorf(pp.Sprintf("expected: %s, actual: %s", tt.changelog.Contents, aClog.Contents))
|
||||
}
|
||||
|
||||
if aClog.Method != tt.changelog.Method {
|
||||
t.Errorf(pp.Sprintf("expected: %s, actual: %s", tt.changelog.Method, aClog.Method))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -332,11 +332,14 @@ func decorateCmd(c conf.ServerInfo, cmd string, sudo bool) string {
|
||||
cmd = strings.Replace(cmd, "sudo -S echo", "echo", -1)
|
||||
}
|
||||
|
||||
if c.Distro.Family != "FreeBSD" {
|
||||
// set pipefail option. Bash only
|
||||
// http://unix.stackexchange.com/questions/14270/get-exit-status-of-process-thats-piped-to-another
|
||||
cmd = fmt.Sprintf("set -o pipefail; %s", cmd)
|
||||
}
|
||||
// If you are using pipe and you want to detect preprocessing errors, remove comment out
|
||||
// switch c.Distro.Family {
|
||||
// case "FreeBSD", "ubuntu", "debian", "raspbian":
|
||||
// default:
|
||||
// // set pipefail option. Bash only
|
||||
// // http://unix.stackexchange.com/questions/14270/get-exit-status-of-process-thats-piped-to-another
|
||||
// cmd = fmt.Sprintf("set -o pipefail; %s", cmd)
|
||||
// }
|
||||
|
||||
if c.IsContainer() {
|
||||
switch c.Container.Type {
|
||||
|
||||
@@ -257,7 +257,7 @@ func (o *redhat) scanUnsecurePackagesUsingYumCheckUpdate() (models.VulnInfos, er
|
||||
cmd = fmt.Sprintf(cmd, "")
|
||||
}
|
||||
|
||||
r := o.exec(util.PrependProxyEnv(cmd), sudo)
|
||||
r := o.exec(util.PrependProxyEnv(cmd), noSudo)
|
||||
if !r.isSuccess(0, 100) {
|
||||
//returns an exit code of 100 if there are available updates.
|
||||
return nil, fmt.Errorf("Failed to SSH: %s", r)
|
||||
@@ -287,11 +287,25 @@ func (o *redhat) scanUnsecurePackagesUsingYumCheckUpdate() (models.VulnInfos, er
|
||||
|
||||
// { packageName: changelog-lines }
|
||||
var rpm2changelog map[string]*string
|
||||
rpm2changelog, err = o.parseAllChangelog(allChangelog)
|
||||
rpm2changelog, err = o.divideChangelogByPackage(allChangelog)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to parseAllChangelog. err: %s", err)
|
||||
}
|
||||
|
||||
for name, clog := range rpm2changelog {
|
||||
for i, p := range o.Packages {
|
||||
n := fmt.Sprintf("%s-%s-%s",
|
||||
p.Name, p.NewVersion, p.NewRelease)
|
||||
if name == n {
|
||||
o.Packages[i].Changelog = models.Changelog{
|
||||
Contents: *clog,
|
||||
Method: models.ChangelogExactMatchStr,
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var results []PackInfoCveIDs
|
||||
for i, packInfo := range packInfoList {
|
||||
changelog := o.getChangelogCVELines(rpm2changelog, packInfo)
|
||||
@@ -452,7 +466,7 @@ func (o *redhat) getChangelogCVELines(rpm2changelog map[string]*string, packInfo
|
||||
return retLine
|
||||
}
|
||||
|
||||
func (o *redhat) parseAllChangelog(allChangelog string) (map[string]*string, error) {
|
||||
func (o *redhat) divideChangelogByPackage(allChangelog string) (map[string]*string, error) {
|
||||
var majorVersion int
|
||||
var err error
|
||||
if o.Distro.Family == "centos" {
|
||||
@@ -559,7 +573,7 @@ func (o *redhat) getAllChangelog(packInfoList models.PackageInfoList) (stdout st
|
||||
"Failed to get changelog. status: %d, stdout: %s, stderr: %s",
|
||||
r.ExitStatus, r.Stdout, r.Stderr)
|
||||
}
|
||||
return r.Stdout, nil
|
||||
return strings.Replace(r.Stdout, "\r", "", -1), nil
|
||||
}
|
||||
|
||||
type distroAdvisoryCveIDs struct {
|
||||
@@ -601,9 +615,8 @@ func (o *redhat) scanUnsecurePackagesUsingYumPluginSecurity() (models.VulnInfos,
|
||||
advIDPackNamesList, err := o.parseYumUpdateinfoListAvailable(r.Stdout)
|
||||
|
||||
// get package name, version, rel to be upgrade.
|
||||
// cmd = "yum check-update --security"
|
||||
cmd = "LANGUAGE=en_US.UTF-8 yum --color=never check-update"
|
||||
r = o.exec(util.PrependProxyEnv(cmd), o.sudo())
|
||||
r = o.exec(util.PrependProxyEnv(cmd), noSudo)
|
||||
if !r.isSuccess(0, 100) {
|
||||
//returns an exit code of 100 if there are available updates.
|
||||
return nil, fmt.Errorf("Failed to SSH: %s", r)
|
||||
|
||||
@@ -1071,7 +1071,7 @@ func TestGetChangelogCVELines(t *testing.T) {
|
||||
Release: "6.7",
|
||||
}
|
||||
for _, tt := range testsCentos6 {
|
||||
rpm2changelog, err := r.parseAllChangelog(stdoutCentos6)
|
||||
rpm2changelog, err := r.divideChangelogByPackage(stdoutCentos6)
|
||||
if err != nil {
|
||||
t.Errorf("err: %s", err)
|
||||
}
|
||||
@@ -1157,7 +1157,7 @@ func TestGetChangelogCVELines(t *testing.T) {
|
||||
Release: "5.6",
|
||||
}
|
||||
for _, tt := range testsCentos5 {
|
||||
rpm2changelog, err := r.parseAllChangelog(stdoutCentos5)
|
||||
rpm2changelog, err := r.divideChangelogByPackage(stdoutCentos5)
|
||||
if err != nil {
|
||||
t.Errorf("err: %s", err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user