v0.5.0 (no backwards compatibility) (#478)

* Change config.toml, Auto-generate UUIDs, change structure of optional field

* Detect processes affected by update using yum-ps (#482)

Detect processes affected by update using yum-ps

* Detect processes needs restart using checkrestart on Debian and Ubuntu.

* pass cpename by args when calling FillCveInfo (#513)

* fix new db (#502)

* Include Version,Revision in JSON

* Include hostname in JSON

* Update goval-dictionary's commit hash in Gopkg.lock

* Remove README.ja.md

* update packages (#596)

* fix: change ControlPath to .vuls of SSH option (#618)

* feat: checkrestart for Ubuntu and Debian (#622)

* feat: checkrestart for Ubuntu and Debian

* fix: dependencies check logic of configtest

* feat: need-restarting on RedHat

* refactor: Process.ProcName to Process.Name

* feat: detect a systemd service name of need-restarting-process

* feat: detect a systemd service name of need-restarting-process on Ubuntu

* feat: fill a service name of need-restarting-process, init-system

* Support NVD JSON and CVSS3 of JVN (#605)

* fix: compile errors

* fix: Show CVSS3 on TUI

* fix: test cases

* fix: Avoid null in JSON

* Fix maxCvssScore (#621)

* Fix maxCvssScore

* Update vulninfos.go

* fix(init): remove unnecessary log initialization

* refactor(nvd): use only json feed if exists json data. if not, use xml feed

* fix(scan): make Confidence slice

* feat(CWE): Display CWE name to TUI

* feat(cwe): import CWE defs in Japanese

* feat(cwe): add OWASP Top 10 ranking to CWE if applicable

* feat(scan): add -fast-root mode, implement scan/amazon.go

* refactor(const): change const name JVN to Jvn

* feat(scan): add -fast-root mode, implement scan/centos.go

* refactor(dep): update deps

* fix(amazon): deps check

* feat(scan): add -fast-root mode, implement scan/rhel.go

* feat(scan): add -fast-root mode, implement scan/oracle.go

* fix complile err

* feat(scan): add -fast-root mode, implement scan/debian.go

* fix testcase

* fix(amazon): scan using yum

* fix(configtest): change error message, status when no scannnable servers

* Fix(scan): detect init process logic

* fix(tui): display cvss as table format

* fix(scan): parse a output of reboot-notifier on CentOS6.9

* fix(tui): don't display score, vector when score is zero

* fix(scan): add -offline mode to suse scanner

* fix(scan): fix help message

* feat(scan): enable to define scan mode for each servers in config.toml #510

* refactor(config): chagne cpeNames to cpeURIs

* refactor(config): change dependencyCheckXMLPath to owaspDCXMLPath

* fix(config): containers -> containersIncluded, Excluded, containerType

* feature(report): enable to define cpeURIs for each contaner

* feature(report): enable to specify owasp dc xml path for each container

* fix(discover): fix a template displayed at the end of discover

* feature(report): add ignorePkgsRegexp #665

* feature(report): enable to define ignoreCves for each container #666

* fix(report): Displayed nothing in TUI detail area when CweID is nil

* Gopkg.toml diet

* feat(server): support server mode (#678)

* feat(server): support server mode

* Lock go version

* Use the latest kernel release among the installed release when the running kernel release is unknown

* Add TestViaHTTP

* Set logger to go-cve-dictionary client

* Add -to-localfile

* Add -to-http option to report

* Load -to-http conf from config.toml

* Support gost (#676)

* feat(gost): Support RedHat API

* feat(gost): Support Debian Security Tracker

* feat(db): display error msg when SQLite3 is locked at the beginning of reporting.

* feat(gost): TUI

* Only use RedHat information of installed packages

* feat(tui): show mitigation on TUI

* feat(gost): support redis backend

* fix test case

* fix nil pointer when db is nil

* fix(gost): detect vulns of src packages for Debian

* feat(gost): implement redis backend for gost redhat api

* feat(report): display fixState of unfixed pkgs

* fix(report): display distincted cweIDs

* feat(slack): display gost info

* feat(slack): display mitigation

* feat(report): display available patch state as fixed/total

* fix(tui): display - if source of reference is empty

* update deps

* fix(report): key in ScanResult JSON be lowerCamelcase.

* some keys to lower camel

* fix(configtest): dep check logic of yum-plugin-ps

* fix(tui): format

* feat(report): add -format-list option

* fix(report): -format-full-text

* fix(report): report -format-full-text

* fix(report): display v3 score detected by gost

* fix(scan): scan in fast mode if not defined in config.toml

* fix(gost): fetch RedHat data for fixed CVEs

* feat(report): show number of cves detected in each database

* fix(report): show new version as `Unknown` in offline and fast scan mode

* fix(report): fix num of upadtable and fixed

* fix(report): set `Not fixed yet` if packageStatus is empty

* refact(gost): make convertToModel public

* fix(test): fix test case

* update deps

* fix(report): include gost score in MaxCvssScore

* [WIP] feat(config): enable to set options in config.toml instead of cmd opt (#690)

* feat(config): enable to set options in config.toml instead of cmd opt

* fix(config): change Conf.Report.Slack to Conf.Slack

* fix(discover): change tempalte

* fix(report): fix config.toml auto-generate with -uuid

* Add endpoint for health check and change endpoint

* refact(cmd): refactor flag set

* fix(report): enable to specify opts with cmd arg and env value

* fix(scan): enable to parse the release version of amazon linux 2

* add(report) add -to-saas option (#695)

* add(report) add -to-saas option

* ignore other writer if -to-saas

* fix(saas) fix bug

* fix(scan): need-restarting needs internet connection

* fix(scan,configtest): check scan mode

* refactor(scan): change func name

* fix(suse): support offline mode, bug fix on AWS, zypper --no-color

* fix(tui): fix nil pointer when no vulns in tui

* feat(report): enable to define CPE FS format in config.toml

* fix(vet): fix warnings of go vet

* fix(travis): go version to 1.11

* update deps
This commit is contained in:
Kota Kanbe
2018-08-27 13:51:09 +09:00
committed by GitHub
parent d785fc2a54
commit 44fa2c5800
82 changed files with 14019 additions and 2485 deletions

View File

@@ -32,7 +32,6 @@ import (
"github.com/google/subcommands"
"github.com/gosuri/uitable"
"github.com/jroimartin/gocui"
log "github.com/sirupsen/logrus"
)
var scanResults models.ScanResults
@@ -55,7 +54,7 @@ func RunTui(results models.ScanResults) subcommands.ExitStatus {
// g, err := gocui.NewGui(gocui.OutputNormal)
g := gocui.NewGui()
if err := g.Init(); err != nil {
log.Errorf("%s", err)
util.Log.Errorf("%s", err)
return subcommands.ExitFailure
}
defer g.Close()
@@ -63,7 +62,7 @@ func RunTui(results models.ScanResults) subcommands.ExitStatus {
g.SetLayout(layout)
// g.SetManagerFunc(layout)
if err := keybindings(g); err != nil {
log.Errorf("%s", err)
util.Log.Errorf("%s", err)
return subcommands.ExitFailure
}
g.SelBgColor = gocui.ColorGreen
@@ -72,7 +71,7 @@ func RunTui(results models.ScanResults) subcommands.ExitStatus {
if err := g.MainLoop(); err != nil {
g.Close()
log.Errorf("%s", err)
util.Log.Errorf("%s", err)
os.Exit(1)
}
return subcommands.ExitSuccess
@@ -468,10 +467,7 @@ 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
return setChangelogLayout(g)
}
func redrawDetail(g *gocui.Gui) error {
@@ -479,10 +475,7 @@ func redrawDetail(g *gocui.Gui) error {
return err
}
if err := setDetailLayout(g); err != nil {
return err
}
return nil
return setDetailLayout(g)
}
func redrawChangelog(g *gocui.Gui) error {
@@ -490,10 +483,7 @@ func redrawChangelog(g *gocui.Gui) error {
return err
}
if err := setChangelogLayout(g); err != nil {
return err
}
return nil
return setChangelogLayout(g)
}
func getLine(g *gocui.Gui, v *gocui.View) error {
@@ -545,10 +535,7 @@ func delMsg(g *gocui.Gui, v *gocui.View) error {
if err := g.DeleteView("msg"); err != nil {
return err
}
if err := g.SetCurrentView("summary"); err != nil {
return err
}
return nil
return g.SetCurrentView("summary")
}
func quit(g *gocui.Gui, v *gocui.View) error {
@@ -565,11 +552,7 @@ func layout(g *gocui.Gui) error {
if err := setDetailLayout(g); err != nil {
return err
}
if err := setChangelogLayout(g); err != nil {
return err
}
return nil
return setChangelogLayout(g)
}
func debug(g *gocui.Gui, str string) error {
@@ -615,7 +598,7 @@ func setSummaryLayout(g *gocui.Gui) error {
return err
}
lines := summaryLines()
lines := summaryLines(currentScanResult)
fmt.Fprintf(v, lines)
v.Highlight = true
@@ -625,37 +608,42 @@ func setSummaryLayout(g *gocui.Gui) error {
return nil
}
func summaryLines() string {
func summaryLines(r models.ScanResult) string {
stable := uitable.New()
stable.MaxColWidth = 1000
stable.Wrap = false
if len(currentScanResult.Errors) != 0 {
if len(r.Errors) != 0 {
return "Error: Scan with --debug to view the details"
}
indexFormat := ""
if len(currentScanResult.ScannedCves) < 10 {
if len(r.ScannedCves) < 10 {
indexFormat = "[%1d]"
} else if len(currentScanResult.ScannedCves) < 100 {
} else if len(r.ScannedCves) < 100 {
indexFormat = "[%2d]"
} else {
indexFormat = "[%3d]"
}
for i, vinfo := range vinfos {
summary := vinfo.Titles(
config.Conf.Lang, currentScanResult.Family)[0].Value
cvssScore := fmt.Sprintf("| %4.1f",
vinfo.MaxCvssScore().Value.Score)
for i, vinfo := range r.ScannedCves.ToSortedSlice() {
max := vinfo.MaxCvssScore().Value.Score
cvssScore := "| "
if 0 < max {
cvssScore = fmt.Sprintf("| %4.1f", max)
}
packname := vinfo.AffectedPackages.FormatTuiSummary()
packname += strings.Join(vinfo.CpeURIs, ", ")
var cols []string
cols = []string{
fmt.Sprintf(indexFormat, i+1),
vinfo.CveID,
cvssScore,
fmt.Sprintf("| %3d |", vinfo.Confidence.Score),
summary,
cvssScore + " |",
fmt.Sprintf("%8s |", vinfo.AttackVector()),
fmt.Sprintf("%7s |", vinfo.PatchStatus(r.Packages)),
packname,
}
icols := make([]interface{}, len(cols))
for j := range cols {
@@ -695,16 +683,12 @@ func setDetailLayout(g *gocui.Gui) error {
}
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()
currentVinfo = cy + oy
maxX, maxY := g.Size()
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
@@ -713,17 +697,56 @@ func setChangelogLayout(g *gocui.Gui) error {
return nil
}
lines := []string{}
lines := []string{
"Affected Packages, Processes",
"============================",
}
_, cy := summaryView.Cursor()
_, oy := summaryView.Origin()
currentVinfo = cy + oy
vinfo := vinfos[currentVinfo]
vinfo.AffectedPackages.Sort()
for _, affected := range vinfo.AffectedPackages {
// packages detected by OVAL may not be actually installed
if pack, ok := currentScanResult.Packages[affected.Name]; ok {
lines = append(lines,
"* "+pack.FormatVersionFromTo(
affected.NotFixedYet, affected.FixState))
if len(pack.AffectedProcs) != 0 {
for _, p := range pack.AffectedProcs {
lines = append(lines, fmt.Sprintf(" * PID: %s %s", p.PID, p.Name))
}
} else {
// lines = append(lines, fmt.Sprintf(" * No affected process"))
}
}
}
sort.Strings(vinfo.CpeURIs)
for _, uri := range vinfo.CpeURIs {
lines = append(lines, "* "+uri)
}
for _, adv := range vinfo.DistroAdvisories {
lines = append(lines, "\n",
"Advisories",
"==========",
)
lines = append(lines, adv.Format())
}
for _, affected := range vinfo.AffectedPackages {
pack := currentScanResult.Packages[affected.Name]
for _, p := range currentScanResult.Packages {
if pack.Name == p.Name {
lines = append(lines, p.FormatChangelog(), "\n")
if currentScanResult.IsDeepScanMode() {
lines = append(lines, "\n",
"ChangeLogs",
"==========",
)
for _, affected := range vinfo.AffectedPackages {
pack := currentScanResult.Packages[affected.Name]
for _, p := range currentScanResult.Packages {
if pack.Name == p.Name {
lines = append(lines, p.FormatChangelog(), "\n")
}
}
}
}
@@ -741,12 +764,13 @@ type dataForTmpl struct {
CveID string
Cvsses string
Summary string
Confidence models.Confidence
Cwes []models.CveContentStr
Mitigation string
Confidences models.Confidences
Cwes []models.CweDictEntry
Links []string
References []models.Reference
Packages []string
CpeNames []string
CpeURIs []string
PublishedDate time.Time
LastModifiedDate time.Time
}
@@ -767,20 +791,6 @@ func detailLines() (string, error) {
}
vinfo := vinfos[currentVinfo]
packsVer := []string{}
vinfo.AffectedPackages.Sort()
for _, affected := range vinfo.AffectedPackages {
// packages detected by OVAL may not be actually installed
if pack, ok := r.Packages[affected.Name]; ok {
packsVer = append(packsVer, pack.FormatVersionFromTo(affected.NotFixedYet))
}
}
sort.Strings(vinfo.CpeNames)
for _, name := range vinfo.CpeNames {
packsVer = append(packsVer, name)
}
links := []string{vinfo.CveContents.SourceLinks(
config.Conf.Lang, r.Family, vinfo.CveID)[0].Value,
vinfo.Cvss2CalcURL(),
@@ -792,35 +802,57 @@ func detailLines() (string, error) {
refs := []models.Reference{}
for _, rr := range vinfo.CveContents.References(r.Family) {
for _, ref := range rr.Value {
if ref.Source == "" {
ref.Source = "-"
}
refs = append(refs, ref)
}
}
summary := vinfo.Summaries(r.Lang, r.Family)[0]
mitigation := vinfo.Mitigations(r.Family)[0]
table := uitable.New()
table.MaxColWidth = maxColWidth
table.Wrap = true
scores := append(vinfo.Cvss3Scores(), vinfo.Cvss2Scores()...)
scores := append(vinfo.Cvss3Scores(), vinfo.Cvss2Scores(r.Family)...)
var cols []interface{}
for _, score := range scores {
if score.Value.Score == 0 && score.Value.Severity == "" {
continue
}
scoreStr := "-"
if 0 < score.Value.Score {
scoreStr = fmt.Sprintf("%3.1f", score.Value.Score)
}
scoreVec := fmt.Sprintf("%s/%s", scoreStr, score.Value.Vector)
cols = []interface{}{
scoreVec,
score.Value.Severity,
score.Value.Format(),
score.Type,
}
table.AddRow(cols...)
}
uniqCweIDs := vinfo.CveContents.UniqCweIDs(r.Family)
cwes := []models.CweDictEntry{}
for _, cweID := range uniqCweIDs {
if strings.HasPrefix(cweID.Value, "CWE-") {
if dict, ok := r.CweDict[strings.TrimPrefix(cweID.Value, "CWE-")]; ok {
cwes = append(cwes, dict)
}
}
}
data := dataForTmpl{
CveID: vinfo.CveID,
Cvsses: fmt.Sprintf("%s\n", table),
Summary: fmt.Sprintf("%s (%s)", summary.Value, summary.Type),
Confidence: vinfo.Confidence,
Cwes: vinfo.CveContents.CweIDs(r.Family),
Links: util.Distinct(links),
Packages: packsVer,
References: refs,
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),
Confidences: vinfo.Confidences,
Cwes: cwes,
Links: util.Distinct(links),
References: refs,
}
buf := bytes.NewBuffer(nil) // create empty buffer
@@ -833,47 +865,41 @@ func detailLines() (string, error) {
const mdTemplate = `
{{.CveID}}
==============
================
CVSS Scores
--------------
-----------
{{.Cvsses }}
Summary
--------------
-----------
{{.Summary }}
Mitigation
-----------
{{.Mitigation }}
Links
--------------
-----------
{{range $link := .Links -}}
* {{$link}}
{{end}}
CWE
--------------
-----------
{{range .Cwes -}}
* {{.Value}} ({{.Type}})
* {{.En.CweID}} [{{.En.Name}}](https://cwe.mitre.org/data/definitions/{{.En.CweID}}.html)
{{end}}
Package/CPE
--------------
{{range $pack := .Packages -}}
* {{$pack}}
{{end -}}
{{range $name := .CpeNames -}}
{{range $name := .CpeURIs -}}
* {{$name}}
{{end}}
Confidence
--------------
{{.Confidence }}
-----------
{{range $confidence := .Confidences -}}
* {{$confidence.DetectionMethod}}
{{end}}
References
--------------
-----------
{{range .References -}}
* [{{.Source}}]( {{.Link}} )
* [{{.Source}}]({{.Link}})
{{end}}
`