Beispiel #1
1
// Scaning unsecure packages using yum-plugin-security.
//TODO return whether already expired.
func (o *redhat) scanUnsecurePackagesUsingYumPluginSecurity() (CvePacksList, error) {
	if o.Family == "centos" {
		// CentOS has no security channel.
		// So use yum check-update && parse changelog
		return CvePacksList{}, fmt.Errorf(
			"yum updateinfo is not suppported on CentOS")
	}

	cmd := "yum --color=never repolist"
	r := o.ssh(util.PrependProxyEnv(cmd), sudo)
	if !r.isSuccess() {
		return nil, fmt.Errorf(
			"Failed to %s. status: %d, stdout: %s, stderr: %s",
			cmd, r.ExitStatus, r.Stdout, r.Stderr)
	}

	// get advisoryID(RHSA, ALAS) - package name,version
	cmd = "yum --color=never updateinfo list available --security"
	r = o.ssh(util.PrependProxyEnv(cmd), sudo)
	if !r.isSuccess() {
		return nil, fmt.Errorf(
			"Failed to %s. status: %d, stdout: %s, stderr: %s",
			cmd, r.ExitStatus, r.Stdout, r.Stderr)
	}
	advIDPackNamesList, err := o.parseYumUpdateinfoListAvailable(r.Stdout)

	// get package name, version, rel to be upgrade.
	//  cmd = "yum check-update --security"
	cmd = "LANG=en_US.UTF-8 yum --color=never check-update"
	r = o.ssh(util.PrependProxyEnv(cmd), sudo)
	if !r.isSuccess(0, 100) {
		//returns an exit code of 100 if there are available updates.
		return nil, fmt.Errorf(
			"Failed to %s. status: %d, stdout: %s, stderr: %s",
			cmd, r.ExitStatus, r.Stdout, r.Stderr)
	}
	updatable, err := o.parseYumCheckUpdateLines(r.Stdout)
	if err != nil {
		return nil, fmt.Errorf("Failed to parse %s. err: %s", cmd, err)
	}
	o.log.Debugf("%s", pp.Sprintf("%v", updatable))

	dict := map[string][]models.PackageInfo{}
	for _, advIDPackNames := range advIDPackNamesList {
		packInfoList := models.PackageInfoList{}
		for _, packName := range advIDPackNames.PackNames {
			packInfo, found := updatable.FindByName(packName)
			if !found {
				return nil, fmt.Errorf(
					"PackInfo not found. packInfo: %#v", packName)
			}
			packInfoList = append(packInfoList, packInfo)
			continue
		}
		dict[advIDPackNames.AdvisoryID] = packInfoList
	}

	// get advisoryID(RHSA, ALAS) - CVE IDs
	cmd = "yum --color=never updateinfo --security update"
	r = o.ssh(util.PrependProxyEnv(cmd), sudo)
	if !r.isSuccess() {
		return nil, fmt.Errorf(
			"Failed to %s. status: %d, stdout: %s, stderr: %s",
			cmd, r.ExitStatus, r.Stdout, r.Stderr)
	}
	advisoryCveIDsList, err := o.parseYumUpdateinfo(r.Stdout)
	if err != nil {
		return CvePacksList{}, err
	}
	//  pp.Println(advisoryCveIDsList)

	// All information collected.
	// Convert to CvePacksList.
	o.log.Info("Fetching CVE details...")
	result := CvePacksList{}
	for _, advIDCveIDs := range advisoryCveIDsList {
		cveDetails, err :=
			cveapi.CveClient.FetchCveDetails(advIDCveIDs.CveIDs)
		if err != nil {
			return nil, err
		}

		for _, cveDetail := range cveDetails {
			found := false
			for i, p := range result {
				if cveDetail.CveID == p.CveID {
					advAppended := append(p.DistroAdvisories, advIDCveIDs.DistroAdvisory)
					result[i].DistroAdvisories = advAppended

					packs := dict[advIDCveIDs.DistroAdvisory.AdvisoryID]
					result[i].Packs = append(result[i].Packs, packs...)
					found = true
					break
				}
			}

			if !found {
				cpinfo := CvePacksInfo{
					CveID:            cveDetail.CveID,
					CveDetail:        cveDetail,
					DistroAdvisories: []models.DistroAdvisory{advIDCveIDs.DistroAdvisory},
					Packs:            dict[advIDCveIDs.DistroAdvisory.AdvisoryID],
				}
				result = append(result, cpinfo)
			}
		}
	}
	o.log.Info("Done")
	return result, nil
}
Beispiel #2
1
// For CentOS
func (o *redhat) scanUnsecurePackagesUsingYumCheckUpdate() (models.VulnInfos, error) {
	cmd := "LANGUAGE=en_US.UTF-8 yum --color=never %s check-update"
	if o.getServerInfo().Enablerepo != "" {
		cmd = fmt.Sprintf(cmd, "--enablerepo="+o.getServerInfo().Enablerepo)
	} else {
		cmd = fmt.Sprintf(cmd, "")
	}

	r := o.exec(util.PrependProxyEnv(cmd), sudo)
	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)
	}

	// get Updateble package name, installed, candidate version.
	packInfoList, err := o.parseYumCheckUpdateLines(r.Stdout)
	if err != nil {
		return nil, fmt.Errorf("Failed to parse %s. err: %s", cmd, err)
	}
	o.log.Debugf("%s", pp.Sprintf("%v", packInfoList))

	// set candidate version info
	o.Packages.MergeNewVersion(packInfoList)

	// Collect CVE-IDs in changelog
	type PackInfoCveIDs struct {
		PackInfo models.PackageInfo
		CveIDs   []string
	}

	allChangelog, err := o.getAllChangelog(packInfoList)
	if err != nil {
		o.log.Errorf("Failed to getAllchangelog. err: %s", err)
		return nil, err
	}

	// { packageName: changelog-lines }
	var rpm2changelog map[string]*string
	rpm2changelog, err = o.parseAllChangelog(allChangelog)
	if err != nil {
		return nil, fmt.Errorf("Failed to parseAllChangelog. err: %s", err)
	}

	var results []PackInfoCveIDs
	for i, packInfo := range packInfoList {
		changelog := o.getChangelogCVELines(rpm2changelog, packInfo)

		// Collect unique set of CVE-ID in each changelog
		uniqueCveIDMap := make(map[string]bool)
		lines := strings.Split(changelog, "\n")
		for _, line := range lines {
			cveIDs := o.parseYumUpdateinfoLineToGetCveIDs(line)
			for _, c := range cveIDs {
				uniqueCveIDMap[c] = true
			}
		}

		// keys
		var cveIDs []string
		for k := range uniqueCveIDMap {
			cveIDs = append(cveIDs, k)
		}
		p := PackInfoCveIDs{
			PackInfo: packInfo,
			CveIDs:   cveIDs,
		}
		results = append(results, p)

		o.log.Infof("(%d/%d) Scanned %s-%s-%s -> %s-%s : %s",
			i+1,
			len(packInfoList),
			p.PackInfo.Name,
			p.PackInfo.Version,
			p.PackInfo.Release,
			p.PackInfo.NewVersion,
			p.PackInfo.NewRelease,
			p.CveIDs)
	}

	// transform datastructure
	// - From
	// [
	//   {
	//     PackInfo:    models.PackageInfo,
	//     CveIDs:      []string,
	//   },
	// ]
	// - To
	// map {
	//   CveID: []models.PackageInfo
	// }
	cveIDPackInfoMap := make(map[string][]models.PackageInfo)
	for _, res := range results {
		for _, cveID := range res.CveIDs {
			cveIDPackInfoMap[cveID] = append(
				cveIDPackInfoMap[cveID], res.PackInfo)
		}
	}

	vinfos := []models.VulnInfo{}
	for k, v := range cveIDPackInfoMap {
		// Amazon, RHEL do not use this method, so VendorAdvisory do not set.
		vinfos = append(vinfos, models.VulnInfo{
			CveID:    k,
			Packages: v,
		})
	}
	return vinfos, nil
}
Beispiel #3
1
//TODO return whether already expired.
func (o *redhat) scanUnsecurePackagesUsingYumCheckUpdate() (CvePacksList, error) {

	cmd := "LANG=en_US.UTF-8 yum --color=never check-update"
	r := o.ssh(util.PrependProxyEnv(cmd), sudo)
	if !r.isSuccess(0, 100) {
		//returns an exit code of 100 if there are available updates.
		return nil, fmt.Errorf(
			"Failed to %s. status: %d, stdout: %s, stderr: %s",
			cmd, r.ExitStatus, r.Stdout, r.Stderr)
	}

	// get Updateble package name, installed, candidate version.
	packInfoList, err := o.parseYumCheckUpdateLines(r.Stdout)
	if err != nil {
		return nil, fmt.Errorf("Failed to parse %s. err: %s", cmd, err)
	}
	o.log.Debugf("%s", pp.Sprintf("%v", packInfoList))

	// Collect CVE-IDs in changelog
	type PackInfoCveIDs struct {
		PackInfo models.PackageInfo
		CveIDs   []string
	}
	var results []PackInfoCveIDs
	for i, packInfo := range packInfoList {
		changelog, err := o.getChangelog(packInfo.Name)
		if err != nil {
			o.log.Errorf("Failed to collect CVE IDs. err: %s", err)
			return nil, err
		}

		// Collect unique set of CVE-ID in each changelog
		uniqueCveIDMap := make(map[string]bool)
		lines := strings.Split(changelog, "\n")
		for _, line := range lines {
			cveIDs := o.parseYumUpdateinfoLineToGetCveIDs(line)
			for _, c := range cveIDs {
				uniqueCveIDMap[c] = true
			}
		}

		// keys
		var cveIDs []string
		for k := range uniqueCveIDMap {
			cveIDs = append(cveIDs, k)
		}
		p := PackInfoCveIDs{
			PackInfo: packInfo,
			CveIDs:   cveIDs,
		}
		results = append(results, p)

		o.log.Infof("(%d/%d) Scanned %s-%s-%s -> %s-%s : %s",
			i+1,
			len(packInfoList),
			p.PackInfo.Name,
			p.PackInfo.Version,
			p.PackInfo.Release,
			p.PackInfo.NewVersion,
			p.PackInfo.NewRelease,
			p.CveIDs)
	}

	// transform datastructure
	// - From
	// [
	//   {
	//     PackInfo:    models.PackageInfo,
	//     CveIDs:      []string,
	//   },
	// ]
	// - To
	// map {
	//   CveID: []models.PackageInfo
	// }
	cveIDPackInfoMap := make(map[string][]models.PackageInfo)
	for _, res := range results {
		for _, cveID := range res.CveIDs {
			//  packInfo, found := o.Packages.FindByName(res.Packname)
			//  if !found {
			//      return CvePacksList{}, fmt.Errorf(
			//          "Faild to transform data structure: %v", res.Packname)
			//  }
			cveIDPackInfoMap[cveID] = append(cveIDPackInfoMap[cveID], res.PackInfo)
		}
	}

	var uniqueCveIDs []string
	for cveID := range cveIDPackInfoMap {
		uniqueCveIDs = append(uniqueCveIDs, cveID)
	}

	// cveIDs => []cve.CveInfo
	o.log.Info("Fetching CVE details...")
	cveDetails, err := cveapi.CveClient.FetchCveDetails(uniqueCveIDs)
	if err != nil {
		return nil, err
	}
	o.log.Info("Done")

	cvePacksList := []CvePacksInfo{}
	for _, detail := range cveDetails {
		// Amazon, RHEL do not use this method, so VendorAdvisory do not set.
		cvePacksList = append(cvePacksList, CvePacksInfo{
			CveID:     detail.CveID,
			CveDetail: detail,
			Packs:     cveIDPackInfoMap[detail.CveID],
			//  CvssScore: cinfo.CvssScore(conf.Lang),
		})
	}
	return cvePacksList, nil
}
Beispiel #4
1
// Scaning unsecure packages using yum-plugin-security.
// Amazon, RHEL
func (o *redhat) scanUnsecurePackagesUsingYumPluginSecurity() (models.VulnInfos, error) {
	if o.Distro.Family == "centos" {
		// CentOS has no security channel.
		// So use yum check-update && parse changelog
		return nil, fmt.Errorf(
			"yum updateinfo is not suppported on CentOS")
	}

	cmd := "yum --color=never repolist"
	r := o.exec(util.PrependProxyEnv(cmd), o.sudo())
	if !r.isSuccess() {
		return nil, fmt.Errorf("Failed to SSH: %s", r)
	}

	// get advisoryID(RHSA, ALAS) - package name,version
	major, err := (o.Distro.MajorVersion())
	if err != nil {
		return nil, fmt.Errorf("Not implemented yet: %s, err: %s", o.Distro, err)
	}

	if o.Distro.Family == "rhel" && major == 5 {
		cmd = "yum --color=never list-security --security"
	} else {
		cmd = "yum --color=never --security updateinfo list updates"
	}
	r = o.exec(util.PrependProxyEnv(cmd), o.sudo())
	if !r.isSuccess() {
		return nil, fmt.Errorf("Failed to SSH: %s", r)
	}
	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())
	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)
	}
	updatable, err := o.parseYumCheckUpdateLines(r.Stdout)
	if err != nil {
		return nil, fmt.Errorf("Failed to parse %s. err: %s", cmd, err)
	}
	o.log.Debugf("%s", pp.Sprintf("%v", updatable))

	// set candidate version info
	o.Packages.MergeNewVersion(updatable)

	dict := map[string][]models.PackageInfo{}
	for _, advIDPackNames := range advIDPackNamesList {
		packInfoList := models.PackageInfoList{}
		for _, packName := range advIDPackNames.PackNames {
			packInfo, found := updatable.FindByName(packName)
			if !found {
				return nil, fmt.Errorf(
					"PackInfo not found. packInfo: %#v", packName)
			}
			packInfoList = append(packInfoList, packInfo)
			continue
		}
		dict[advIDPackNames.AdvisoryID] = packInfoList
	}

	// get advisoryID(RHSA, ALAS) - CVE IDs
	if o.Distro.Family == "rhel" && major == 5 {
		cmd = "yum --color=never info-sec"
	} else {
		cmd = "yum --color=never --security updateinfo updates"
	}
	r = o.exec(util.PrependProxyEnv(cmd), o.sudo())
	if !r.isSuccess() {
		return nil, fmt.Errorf("Failed to SSH: %s", r)
	}
	advisoryCveIDsList, err := o.parseYumUpdateinfo(r.Stdout)
	if err != nil {
		return nil, err
	}
	//  pp.Println(advisoryCveIDsList)

	// All information collected.
	// Convert to VulnInfos.
	vinfos := models.VulnInfos{}
	for _, advIDCveIDs := range advisoryCveIDsList {
		for _, cveID := range advIDCveIDs.CveIDs {
			found := false
			for i, p := range vinfos {
				if cveID == p.CveID {
					advAppended := append(p.DistroAdvisories, advIDCveIDs.DistroAdvisory)
					vinfos[i].DistroAdvisories = advAppended

					packs := dict[advIDCveIDs.DistroAdvisory.AdvisoryID]
					vinfos[i].Packages = append(vinfos[i].Packages, packs...)
					found = true
					break
				}
			}

			if !found {
				cpinfo := models.VulnInfo{
					CveID:            cveID,
					DistroAdvisories: []models.DistroAdvisory{advIDCveIDs.DistroAdvisory},
					Packages:         dict[advIDCveIDs.DistroAdvisory.AdvisoryID],
				}
				vinfos = append(vinfos, cpinfo)
			}

		}
	}
	return vinfos, nil
}
Beispiel #5
0
func (o *debian) install() error {
	if len(o.lackDependencies) == 0 {
		return nil
	}

	// apt-get update
	o.log.Infof("apt-get update...")
	cmd := util.PrependProxyEnv("apt-get update")
	if r := o.exec(cmd, sudo); !r.isSuccess() {
		msg := fmt.Sprintf("Failed to SSH: %s", r)
		o.log.Errorf(msg)
		return fmt.Errorf(msg)
	}

	for _, name := range o.lackDependencies {
		cmd = util.PrependProxyEnv("apt-get install -y " + name)
		if r := o.exec(cmd, sudo); !r.isSuccess() {
			msg := fmt.Sprintf("Failed to SSH: %s", r)
			o.log.Errorf(msg)
			return fmt.Errorf(msg)
		}
		o.log.Infof("Installed: " + name)
	}
	return nil
}
Beispiel #6
0
func (o *debian) GetUnsecurePackNamesUsingUnattendedUpgrades() (packNames []string, err error) {
	cmd := util.PrependProxyEnv("unattended-upgrades --dry-run -d 2>&1 ")
	release, err := strconv.ParseFloat(o.Release, 64)
	if err != nil {
		return packNames, fmt.Errorf(
			"OS Release Version is invalid, %s, %s", o.Family, o.Release)
	}
	switch {
	case release < 12:
		return packNames, fmt.Errorf(
			"Support expired. %s, %s", o.Family, o.Release)

	case 12 < release && release < 14:
		cmd += `| grep 'pkgs that look like they should be upgraded:' |
			sed -e 's/pkgs that look like they should be upgraded://g'`

	case 14 < release:
		cmd += `| grep 'Packages that will be upgraded:' |
			sed -e 's/Packages that will be upgraded://g'`

	default:
		return packNames, fmt.Errorf(
			"Not supported yet. %s, %s", o.Family, o.Release)
	}

	r := o.ssh(cmd, sudo)
	if r.isSuccess(0, 1) {
		packNames = strings.Split(strings.TrimSpace(r.Stdout), " ")
		return packNames, nil
	}

	return packNames, fmt.Errorf(
		"Failed to %s. status: %d, stdout: %s, stderr: %s",
		cmd, r.ExitStatus, r.Stdout, r.Stderr)
}
Beispiel #7
0
func (o *debian) scanPackageCveIDs(pack models.PackageInfo) ([]string, error) {
	cmd := ""
	switch o.Distro.Family {
	case "ubuntu":
		cmd = fmt.Sprintf(`apt-get changelog %s | grep '\(urgency\|CVE\)'`, pack.Name)
	case "debian":
		cmd = fmt.Sprintf(`aptitude changelog %s | grep '\(urgency\|CVE\)'`, pack.Name)
	}
	cmd = util.PrependProxyEnv(cmd)

	r := o.exec(cmd, noSudo)
	if !r.isSuccess() {
		o.log.Warnf("Failed to SSH: %s", r)
		// Ignore this Error.
		return nil, nil
	}

	if 0 < len(strings.TrimSpace(r.Stdout)) {
		err := cache.DB.PutChangelog(o.getServerInfo().GetServerName(), pack.Name, r.Stdout)
		if err != nil {
			return nil, fmt.Errorf("Failed to put changelog into cache")
		}
	}
	// No error will be returned. Only logging.
	return o.getCveIDFromChangelog(r.Stdout, pack.Name, pack.Version), nil
}
Beispiel #8
0
func (o *debian) install() error {

	// apt-get update
	o.log.Infof("apt-get update...")
	cmd := util.PrependProxyEnv("apt-get update")
	if r := o.ssh(cmd, sudo); !r.isSuccess() {
		msg := fmt.Sprintf("Failed to %s. status: %d, stdout: %s, stderr: %s",
			cmd, r.ExitStatus, r.Stdout, r.Stderr)
		o.log.Errorf(msg)
		return fmt.Errorf(msg)
	}

	if o.Family == "debian" {
		// install aptitude
		cmd = util.PrependProxyEnv("apt-get install --force-yes -y aptitude")
		if r := o.ssh(cmd, sudo); !r.isSuccess() {
			msg := fmt.Sprintf("Failed to %s. status: %d, stdout: %s, stderr: %s",
				cmd, r.ExitStatus, r.Stdout, r.Stderr)
			o.log.Errorf(msg)
			return fmt.Errorf(msg)
		}
		o.log.Infof("Installed: aptitude")
	}

	// install unattended-upgrades
	if !config.Conf.UseUnattendedUpgrades {
		return nil
	}

	if r := o.ssh("type unattended-upgrade", noSudo); r.isSuccess() {
		o.log.Infof(
			"Ignored: unattended-upgrade already installed")
		return nil
	}

	cmd = util.PrependProxyEnv(
		"apt-get install --force-yes -y unattended-upgrades")
	if r := o.ssh(cmd, sudo); !r.isSuccess() {
		msg := fmt.Sprintf("Failed to %s. status: %d, stdout: %s, stderr: %s",
			cmd, r.ExitStatus, r.Stdout, r.Stderr)
		o.log.Errorf(msg)
		return fmt.Errorf(msg)
	}

	o.log.Infof("Installed: unattended-upgrades")
	return nil
}
Beispiel #9
0
func (o *bsd) scanInstalledPackages() ([]models.PackageInfo, error) {
	cmd := util.PrependProxyEnv("pkg version -v")
	r := o.exec(cmd, noSudo)
	if !r.isSuccess() {
		return nil, fmt.Errorf("Failed to SSH: %s", r)
	}
	return o.parsePkgVersion(r.Stdout), nil
}
Beispiel #10
0
func (o *bsd) scanInstalledPackages() ([]models.PackageInfo, error) {
	cmd := util.PrependProxyEnv("pkg version -v")
	r := o.ssh(cmd, noSudo)
	if !r.isSuccess() {
		return nil, fmt.Errorf("Failed to %s. status: %d, stdout:%s, Stderr: %s",
			cmd, r.ExitStatus, r.Stdout, r.Stderr)
	}
	return o.parsePkgVersion(r.Stdout), nil
}
Beispiel #11
0
func (o *debian) GetUpgradablePackNames() (packNames []string, err error) {
	cmd := util.PrependProxyEnv("LANGUAGE=en_US.UTF-8 apt-get upgrade --dry-run")
	r := o.exec(cmd, sudo)
	if r.isSuccess(0, 1) {
		return o.parseAptGetUpgrade(r.Stdout)
	}
	return packNames, fmt.Errorf(
		"Failed to %s. status: %d, stdout: %s, stderr: %s",
		cmd, r.ExitStatus, r.Stdout, r.Stderr)
}
Beispiel #12
0
func (o *redhat) install() error {
	for _, name := range o.lackDependencies {
		cmd := util.PrependProxyEnv("yum install -y " + name)
		if r := o.exec(cmd, sudo); !r.isSuccess() {
			return fmt.Errorf("Failed to SSH: %s", r)
		}
		o.log.Infof("Installed: %s", name)
	}
	return nil
}
Beispiel #13
0
func (o *debian) scanUnsecurePackages(installed []models.PackageInfo) ([]models.VulnInfo, error) {
	o.log.Infof("apt-get update...")
	cmd := util.PrependProxyEnv("apt-get update")
	if r := o.exec(cmd, sudo); !r.isSuccess() {
		return nil, fmt.Errorf("Failed to SSH: %s", r)
	}

	// Convert the name of upgradable packages to PackageInfo struct
	upgradableNames, err := o.GetUpgradablePackNames()
	if err != nil {
		return nil, err
	}
	var upgradablePacks []models.PackageInfo
	for _, name := range upgradableNames {
		for _, pack := range installed {
			if pack.Name == name {
				upgradablePacks = append(upgradablePacks, pack)
				break
			}
		}
	}

	// Fill the candidate versions of upgradable packages
	upgradablePacks, err = o.fillCandidateVersion(upgradablePacks)
	if err != nil {
		return nil, fmt.Errorf("Failed to fill candidate versions. err: %s", err)
	}

	o.Packages.MergeNewVersion(upgradablePacks)

	// Setup changelog cache
	current := cache.Meta{
		Name:   o.getServerInfo().GetServerName(),
		Distro: o.getServerInfo().Distro,
		Packs:  upgradablePacks,
	}

	o.log.Debugf("Ensure changelog cache: %s", current.Name)
	var meta *cache.Meta
	if meta, err = o.ensureChangelogCache(current); err != nil {
		return nil, err
	}

	// Collect CVE information of upgradable packages
	vulnInfos, err := o.scanVulnInfos(upgradablePacks, meta)
	if err != nil {
		return nil, fmt.Errorf("Failed to scan unsecure packages. err: %s", err)
	}

	return vulnInfos, nil
}
Beispiel #14
0
//TODO return whether already expired.
func (o *debian) scanUnsecurePackages(packs []models.PackageInfo) ([]CvePacksInfo, error) {
	//  cmd := prependProxyEnv(conf.HTTPProxy, "apt-get update | cat; echo 1")
	cmd := util.PrependProxyEnv("apt-get update")
	if r := o.ssh(cmd, sudo); !r.isSuccess() {
		return nil, fmt.Errorf(
			"Failed to %s. status: %d, stdout: %s, stderr: %s",
			cmd, r.ExitStatus, r.Stdout, r.Stderr,
		)
	}

	var upgradablePackNames []string
	var err error
	if config.Conf.UseUnattendedUpgrades {
		upgradablePackNames, err = o.GetUnsecurePackNamesUsingUnattendedUpgrades()
		if err != nil {
			return []CvePacksInfo{}, err
		}
	} else {
		upgradablePackNames, err = o.GetUpgradablePackNames()
		if err != nil {
			return []CvePacksInfo{}, err
		}
	}

	// Convert package name to PackageInfo struct
	var unsecurePacks []models.PackageInfo
	for _, name := range upgradablePackNames {
		for _, pack := range packs {
			if pack.Name == name {
				unsecurePacks = append(unsecurePacks, pack)
				break
			}
		}
	}

	unsecurePacks, err = o.fillCandidateVersion(unsecurePacks)
	if err != nil {
		return nil, fmt.Errorf("Failed to fill candidate versions. err: %s", err)
	}

	// Collect CVE information of upgradable packages
	cvePacksInfos, err := o.scanPackageCveInfos(unsecurePacks)
	if err != nil {
		return nil, fmt.Errorf("Failed to scan unsecure packages. err: %s", err)
	}

	return cvePacksInfos, nil
}
Beispiel #15
0
func (o *redhat) installYumPluginSecurity() error {

	if r := o.ssh("rpm -q yum-plugin-security", noSudo); r.isSuccess() {
		o.log.Infof("Ignored: yum-plugin-security already installed")
		return nil
	}

	o.log.Info("Installing yum-plugin-security...")
	cmd := util.PrependProxyEnv("yum install -y yum-plugin-security")
	if r := o.ssh(cmd, sudo); !r.isSuccess() {
		return fmt.Errorf(
			"Failed to %s. status: %d, stdout: %s, stderr: %s",
			cmd, r.ExitStatus, r.Stdout, r.Stderr)
	}
	return nil
}
Beispiel #16
0
func (o *debian) scanPackageCveIDs(pack models.PackageInfo) ([]string, error) {
	cmd := ""
	switch o.Family {
	case "ubuntu":
		cmd = fmt.Sprintf(`apt-get changelog %s | grep '\(urgency\|CVE\)'`, pack.Name)
	case "debian":
		cmd = fmt.Sprintf(`aptitude changelog %s | grep '\(urgency\|CVE\)'`, pack.Name)
	}
	cmd = util.PrependProxyEnv(cmd)

	r := o.ssh(cmd, noSudo)
	if !r.isSuccess() {
		o.log.Warnf(
			"Failed to %s. status: %d, stdout: %s, stderr: %s",
			cmd, r.ExitStatus, r.Stdout, r.Stderr)
		// Ignore this Error.
		return nil, nil

	}
	return o.getCveIDParsingChangelog(r.Stdout, pack.Name, pack.Version)
}
Beispiel #17
0
func (o *redhat) installYumChangelog() error {

	if o.Family == "centos" {
		var majorVersion int
		if 0 < len(o.Release) {
			majorVersion, _ = strconv.Atoi(strings.Split(o.Release, ".")[0])
		} else {
			return fmt.Errorf(
				"Not implemented yet. family: %s, release: %s",
				o.Family, o.Release)
		}

		var packName = ""
		if majorVersion < 6 {
			packName = "yum-changelog"
		} else {
			packName = "yum-plugin-changelog"
		}

		cmd := "rpm -q " + packName
		if r := o.ssh(cmd, noSudo); r.isSuccess() {
			o.log.Infof("Ignored: %s already installed", packName)
			return nil
		}

		o.log.Infof("Installing %s...", packName)
		cmd = util.PrependProxyEnv("yum install -y " + packName)
		if r := o.ssh(cmd, sudo); !r.isSuccess() {
			return fmt.Errorf(
				"Failed to install %s. status: %d, stdout: %s, stderr: %s",
				packName, r.ExitStatus, r.Stdout, r.Stderr)
		}
		o.log.Infof("Installed: %s", packName)
	}
	return nil
}
Beispiel #18
0
func (o *bsd) scanUnsecurePackages() (vulnInfos []models.VulnInfo, err error) {
	const vulndbPath = "/tmp/vuln.db"
	cmd := "rm -f " + vulndbPath
	r := o.exec(cmd, noSudo)
	if !r.isSuccess(0) {
		return nil, fmt.Errorf("Failed to SSH: %s", r)
	}

	cmd = util.PrependProxyEnv("pkg audit -F -r -f " + vulndbPath)
	r = o.exec(cmd, noSudo)
	if !r.isSuccess(0, 1) {
		return nil, fmt.Errorf("Failed to SSH: %s", r)
	}
	if r.ExitStatus == 0 {
		// no vulnerabilities
		return []models.VulnInfo{}, nil
	}

	var packAdtRslt []pkgAuditResult
	blocks := o.splitIntoBlocks(r.Stdout)
	for _, b := range blocks {
		name, cveIDs, vulnID := o.parseBlock(b)
		if len(cveIDs) == 0 {
			continue
		}
		pack, found := o.Packages.FindByName(name)
		if !found {
			return nil, fmt.Errorf("Vulnerable package: %s is not found", name)
		}
		packAdtRslt = append(packAdtRslt, pkgAuditResult{
			pack: pack,
			vulnIDCveIDs: vulnIDCveIDs{
				vulnID: vulnID,
				cveIDs: cveIDs,
			},
		})
	}

	// { CVE ID: []pkgAuditResult }
	cveIDAdtMap := make(map[string][]pkgAuditResult)
	for _, p := range packAdtRslt {
		for _, cid := range p.vulnIDCveIDs.cveIDs {
			cveIDAdtMap[cid] = append(cveIDAdtMap[cid], p)
		}
	}

	for k := range cveIDAdtMap {
		packs := []models.PackageInfo{}
		for _, r := range cveIDAdtMap[k] {
			packs = append(packs, r.pack)
		}

		disAdvs := []models.DistroAdvisory{}
		for _, r := range cveIDAdtMap[k] {
			disAdvs = append(disAdvs, models.DistroAdvisory{
				AdvisoryID: r.vulnIDCveIDs.vulnID,
			})
		}

		vulnInfos = append(vulnInfos, models.VulnInfo{
			CveID:            k,
			Packages:         packs,
			DistroAdvisories: disAdvs,
		})
	}
	return
}
Beispiel #19
0
func (o *bsd) scanUnsecurePackages() (cvePacksList []CvePacksInfo, err error) {
	const vulndbPath = "/tmp/vuln.db"
	cmd := "rm -f " + vulndbPath
	r := o.ssh(cmd, noSudo)
	if !r.isSuccess(0) {
		return nil, fmt.Errorf("Failed to %s. status: %d, stdout:%s, Stderr: %s",
			cmd, r.ExitStatus, r.Stdout, r.Stderr)
	}

	cmd = util.PrependProxyEnv("pkg audit -F -r -f " + vulndbPath)
	r = o.ssh(cmd, noSudo)
	if !r.isSuccess(0, 1) {
		return nil, fmt.Errorf("Failed to %s. status: %d, stdout:%s, Stderr: %s",
			cmd, r.ExitStatus, r.Stdout, r.Stderr)
	}
	if r.ExitStatus == 0 {
		// no vulnerabilities
		return []CvePacksInfo{}, nil
	}

	var packAdtRslt []pkgAuditResult
	blocks := o.splitIntoBlocks(r.Stdout)
	for _, b := range blocks {
		name, cveIDs, vulnID := o.parseBlock(b)
		if len(cveIDs) == 0 {
			continue
		}
		pack, found := o.Packages.FindByName(name)
		if !found {
			return nil, fmt.Errorf("Vulnerable package: %s is not found", name)
		}
		packAdtRslt = append(packAdtRslt, pkgAuditResult{
			pack: pack,
			vulnIDCveIDs: vulnIDCveIDs{
				vulnID: vulnID,
				cveIDs: cveIDs,
			},
		})
	}

	// { CVE ID: []pkgAuditResult }
	cveIDAdtMap := make(map[string][]pkgAuditResult)
	for _, p := range packAdtRslt {
		for _, cid := range p.vulnIDCveIDs.cveIDs {
			cveIDAdtMap[cid] = append(cveIDAdtMap[cid], p)
		}
	}

	cveIDs := []string{}
	for k := range cveIDAdtMap {
		cveIDs = append(cveIDs, k)
	}

	cveDetails, err := cveapi.CveClient.FetchCveDetails(cveIDs)
	if err != nil {
		return nil, err
	}
	o.log.Info("Done")

	for _, d := range cveDetails {
		packs := []models.PackageInfo{}
		for _, r := range cveIDAdtMap[d.CveID] {
			packs = append(packs, r.pack)
		}

		disAdvs := []models.DistroAdvisory{}
		for _, r := range cveIDAdtMap[d.CveID] {
			disAdvs = append(disAdvs, models.DistroAdvisory{
				AdvisoryID: r.vulnIDCveIDs.vulnID,
			})
		}

		cvePacksList = append(cvePacksList, CvePacksInfo{
			CveID:            d.CveID,
			CveDetail:        d,
			Packs:            packs,
			DistroAdvisories: disAdvs,
		})
	}
	return
}