Handle kernel's vulns using OVAL

This commit is contained in:
kota kanbe
2017-08-22 17:44:50 +09:00
parent 93f741da35
commit b5cb08ac43
14 changed files with 417 additions and 329 deletions

View File

@@ -29,40 +29,6 @@ type DebianBase struct {
Base
}
// FillWithOval returns scan result after updating CVE info by OVAL
func (o DebianBase) FillWithOval(r *models.ScanResult) (err error) {
var relatedDefs ovalResult
if o.isFetchViaHTTP() {
if relatedDefs, err = getDefsByPackNameViaHTTP(r); err != nil {
return err
}
} else {
if relatedDefs, err = getDefsByPackNameFromOvalDB(o.family, r.Release, r.Packages); err != nil {
return err
}
}
for _, defPacks := range relatedDefs.entries {
o.update(r, defPacks)
}
for _, vuln := range r.ScannedCves {
switch models.NewCveContentType(o.family) {
case models.Debian:
if cont, ok := vuln.CveContents[models.Debian]; ok {
cont.SourceLink = "https://security-tracker.debian.org/tracker/" + cont.CveID
vuln.CveContents[models.Debian] = cont
}
case models.Ubuntu:
if cont, ok := vuln.CveContents[models.Ubuntu]; ok {
cont.SourceLink = "http://people.ubuntu.com/~ubuntu-security/cve/" + cont.CveID
vuln.CveContents[models.Ubuntu] = cont
}
}
}
return nil
}
func (o DebianBase) update(r *models.ScanResult, defPacks defPacks) {
ovalContent := *o.convertToModel(&defPacks.def)
ovalContent.Type = models.NewCveContentType(o.family)
@@ -136,6 +102,57 @@ func NewDebian() Debian {
}
}
// FillWithOval returns scan result after updating CVE info by OVAL
func (o Debian) FillWithOval(r *models.ScanResult) (err error) {
//Debian's uname gives both of kernel release(uname -r), version(kernel-image version)
linuxImage := "linux-image-" + r.RunningKernel.Release
// Add linux and set the version of running kernel to search OVAL.
if r.Container.ContainerID == "" {
r.Packages["linux"] = models.Package{
Name: "linux",
Version: r.RunningKernel.Version,
}
}
var relatedDefs ovalResult
if o.isFetchViaHTTP() {
if relatedDefs, err = getDefsByPackNameViaHTTP(r); err != nil {
return err
}
} else {
if relatedDefs, err = getDefsByPackNameFromOvalDB(o.family, r.Release, r.Packages); err != nil {
return err
}
}
delete(r.Packages, "linux")
for _, defPacks := range relatedDefs.entries {
// Remove linux added above to search for oval
// linux is not a real package name (key of affected packages in OVAL)
if _, ok := defPacks.actuallyAffectedPackNames["linux"]; ok {
defPacks.actuallyAffectedPackNames[linuxImage] = true
delete(defPacks.actuallyAffectedPackNames, "linux")
for i, p := range defPacks.def.AffectedPacks {
if p.Name == "linux" {
p.Name = linuxImage
defPacks.def.AffectedPacks[i] = p
}
}
}
o.update(r, defPacks)
}
for _, vuln := range r.ScannedCves {
if cont, ok := vuln.CveContents[models.Debian]; ok {
cont.SourceLink = "https://security-tracker.debian.org/tracker/" + cont.CveID
vuln.CveContents[models.Debian] = cont
}
}
return nil
}
// Ubuntu is the interface for Debian OVAL
type Ubuntu struct {
DebianBase
@@ -151,3 +168,99 @@ func NewUbuntu() Ubuntu {
},
}
}
// FillWithOval returns scan result after updating CVE info by OVAL
func (o Ubuntu) FillWithOval(r *models.ScanResult) (err error) {
ovalKernelImageNames := []string{
"linux-aws",
"linux-azure",
"linux-flo",
"linux-gcp",
"linux-gke",
"linux-goldfish",
"linux-hwe",
"linux-hwe-edge",
"linux-kvm",
"linux-mako",
"linux-raspi2",
"linux-snapdragon",
}
linuxImage := "linux-image-" + r.RunningKernel.Release
found := false
if r.Container.ContainerID == "" {
for _, n := range ovalKernelImageNames {
if _, ok := r.Packages[n]; ok {
v, ok := r.Packages[linuxImage]
if ok {
// Set running kernel version
p := r.Packages[n]
p.Version = v.Version
p.NewVersion = v.NewVersion
r.Packages[n] = p
} else {
util.Log.Warnf("Running kernel image %s is not found: %s",
linuxImage, r.RunningKernel.Version)
}
found = true
break
}
}
if !found {
// linux-generic is described as "linux" in Ubuntu's oval.
// Add "linux" and set the version of running kernel to search OVAL.
v, ok := r.Packages[linuxImage]
if ok {
r.Packages["linux"] = models.Package{
Name: "linux",
Version: v.Version,
NewVersion: v.NewVersion,
}
} else {
util.Log.Warnf("%s is not found. Running: %s",
linuxImage, r.RunningKernel.Release)
}
}
}
var relatedDefs ovalResult
if o.isFetchViaHTTP() {
if relatedDefs, err = getDefsByPackNameViaHTTP(r); err != nil {
return err
}
} else {
if relatedDefs, err = getDefsByPackNameFromOvalDB(o.family, r.Release, r.Packages); err != nil {
return err
}
}
if !found {
delete(r.Packages, "linux")
}
for _, defPacks := range relatedDefs.entries {
// Remove "linux" added above to search for oval
// "linux" is not a real package name (key of affected packages in OVAL)
if _, ok := defPacks.actuallyAffectedPackNames["linux"]; !found && ok {
defPacks.actuallyAffectedPackNames[linuxImage] = true
delete(defPacks.actuallyAffectedPackNames, "linux")
for i, p := range defPacks.def.AffectedPacks {
if p.Name == "linux" {
p.Name = linuxImage
defPacks.def.AffectedPacks[i] = p
}
}
}
o.update(r, defPacks)
}
for _, vuln := range r.ScannedCves {
if cont, ok := vuln.CveContents[models.Ubuntu]; ok {
cont.SourceLink = "http://people.ubuntu.com/~ubuntu-security/cve/" + cont.CveID
vuln.CveContents[models.Ubuntu] = cont
}
}
return nil
}

View File

@@ -146,8 +146,5 @@ func (b Base) CheckIfOvalFresh(osFamily, release string) (ok bool, err error) {
func (b Base) isFetchViaHTTP() bool {
// Default value of OvalDBType is sqlite3
if config.Conf.OvalDBURL != "" && config.Conf.OvalDBType == "sqlite3" {
return true
}
return false
return config.Conf.OvalDBURL != "" && config.Conf.OvalDBType == "sqlite3"
}

View File

@@ -58,7 +58,7 @@ func (e defPacks) toPackStatuses(family string, packs models.Packages) (ps model
})
}
case config.CentOS:
case config.CentOS, config.Debian:
// There are many packages that has been fixed in RedHat, but not been fixed in CentOS
for name := range e.actuallyAffectedPackNames {
pack, ok := packs[name]
@@ -79,8 +79,7 @@ func (e defPacks) toPackStatuses(family string, packs models.Packages) (ps model
return
}
packNewVer := fmt.Sprintf("%s-%s", pack.NewVersion, pack.NewRelease)
if packNewVer == "" {
if pack.NewVersion == "" {
// compare version: installed vs oval
vera := rpmver.NewVersion(fmt.Sprintf("%s-%s", pack.Version, pack.Release))
verb := rpmver.NewVersion(ovalPackVer)
@@ -94,6 +93,7 @@ func (e defPacks) toPackStatuses(family string, packs models.Packages) (ps model
})
} else {
// compare version: newVer vs oval
packNewVer := fmt.Sprintf("%s-%s", pack.NewVersion, pack.NewRelease)
vera := rpmver.NewVersion(packNewVer)
verb := rpmver.NewVersion(ovalPackVer)
notFixedYet := false
@@ -193,11 +193,15 @@ func getDefsByPackNameViaHTTP(r *models.ScanResult) (
if res.pack.Name != p.Name {
continue
}
if p.NotFixedYet {
relatedDefs.upsert(def, p.Name)
continue
}
if less, err := lessThan(r.Family, *res.pack, p); err != nil {
if !p.NotFixedYet {
util.Log.Debugf("Failed to parse versions: %s", err)
util.Log.Debugf("%#v\n%#v", *res.pack, p)
}
util.Log.Debugf("Failed to parse versions: %s", err)
util.Log.Debugf("%#v\n%#v", *res.pack, p)
} else if less {
relatedDefs.upsert(def, p.Name)
}
@@ -278,23 +282,28 @@ func getDefsByPackNameFromOvalDB(family, osRelease string,
return
}
defer ovaldb.CloseDB()
for _, pack := range installedPacks {
definitions, err := ovaldb.GetByPackName(osRelease, pack.Name)
for _, installedPack := range installedPacks {
definitions, err := ovaldb.GetByPackName(osRelease, installedPack.Name)
if err != nil {
return relatedDefs, fmt.Errorf("Failed to get %s OVAL info by package name: %v", family, err)
}
for _, def := range definitions {
for _, p := range def.AffectedPacks {
if pack.Name != p.Name {
for _, ovalPack := range def.AffectedPacks {
if installedPack.Name != ovalPack.Name {
continue
}
if less, err := lessThan(family, pack, p); err != nil {
if !p.NotFixedYet {
util.Log.Debugf("Failed to parse versions: %s", err)
util.Log.Debugf("%#v\n%#v", pack, p)
}
if ovalPack.NotFixedYet {
relatedDefs.upsert(def, installedPack.Name)
continue
}
less, err := lessThan(family, installedPack, ovalPack)
if err != nil {
util.Log.Debugf("Failed to parse versions: %s", err)
util.Log.Debugf("%#v\n%#v", installedPack, ovalPack)
} else if less {
relatedDefs.upsert(def, pack.Name)
relatedDefs.upsert(def, installedPack.Name)
}
}
}