Handle kernel's vulns using OVAL
This commit is contained in:
		
							
								
								
									
										181
									
								
								oval/debian.go
									
									
									
									
									
								
							
							
						
						
									
										181
									
								
								oval/debian.go
									
									
									
									
									
								
							@@ -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
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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"
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										43
									
								
								oval/util.go
									
									
									
									
									
								
							
							
						
						
									
										43
									
								
								oval/util.go
									
									
									
									
									
								
							@@ -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)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user