导语:容器技术在google推广之下,目前已经在得到广泛的应用,越来越多的企业借助云计算为企业提质增效,实现产业升级,随着应用程序在云中大规模部署,导致云环境的复杂性不断增加,越来越多的互联网应用在云上遇到挑战,企业需要更高效的应用管理和更弹性的计算架构。
0x00、业务需求
容器技术在google推广之下,目前已经在得到广泛的应用,越来越多的企业借助云计算为企业提质增效,实现产业升级,随着应用程序在云中大规模部署,导致云环境的复杂性不断增加,越来越多的互联网应用在云上遇到挑战,企业需要更高效的应用管理和更弹性的计算架构。以 Kubernetes 为代表的云原生技术让“云原生”从一个模糊的概念,强势成长为通用技术。灵雀云、linkcloud等第三方厂商也不断涌出,同时,云原生的容器云也在各大公有云厂商中快速部署、实践、产品化。
在这种大背景下,很多使用场景都涌现出来:
1、DevOps场景
2、IoT Egde边缘计算端
3、公有云容器集群
4、私有化平台集成
5、…
在这种的大背景下,容器安全是一个必须考虑的一个问题,今天就和大家讨论一下,其中一项docker镜像扫描。
0x01、容器漏洞扫描原理
软件漏洞是软件或操作系统中存在缺陷或弱点,容器漏洞扫描系统需要具备:针对操作系统软件包(RedHat、CentOS,Debian,Ubuntu),应用程序依赖项(nodejs,php,npm,yarn,python等)进行扫描,同时方便集成devops(例如:Jenkins、镜像仓库等)。精确度高(特别是Alpine Linux和RHEL /CentOS)
漏洞扫描最重要是拥有一个强大的漏洞库,
可以收集:https://github.com/aquasecurity/vuln-list/tree/master/alpine
{ "IssueID": 0, "VulnerabilityID": "CVE-2019-5736", "Release": "3.9", "Package": "runc", "Repository": "community", "FixedVersion": "1.0.0_rc6-r1", "Subject": "", "Description": "" } 其中VulnerabilityID、Package、FixedVersion,组成了版本比对数据库。当然可以通过CNVD关联的CVE号补充Subject、Description。漏洞总数超过1万+
扫描器检查部分代码(以ubuntu为例): 第三方库支持:bundler、cargo、composer、npm、pipenv、poetry、yarn、node、python 获取原始版本: func (s *Scanner) Detect(osVer string, pkgs []analyzer.Package) ([]vulnerability.DetectedVulnerability, error) { log.Logger.Info("Detecting Ubuntu vulnerabilities...") log.Logger.Debugf("ubuntu: os version: %s", osVer) log.Logger.Debugf("ubuntu: the number of packages: %d", len(pkgs)) var vulns []vulnerability.DetectedVulnerability for _, pkg := range pkgs { advisories, err := ubuntu.Get(osVer, pkg.SrcName) if err != nil { return nil, xerrors.Errorf("failed to get Ubuntu advisories: %w", err) } installed := utils.FormatSrcVersion(pkg) installedVersion, err := version.NewVersion(installed) if err != nil { log.Logger.Debugf("failed to parse Ubuntu installed package version: %w", err) continue } for _, adv := range advisories { vuln := vulnerability.DetectedVulnerability{ VulnerabilityID: adv.VulnerabilityID, PkgName: pkg.Name, InstalledVersion: installed, FixedVersion: adv.FixedVersion, } if adv.FixedVersion == "" { vulns = append(vulns, vuln) continue } fixedVersion, err := version.NewVersion(adv.FixedVersion) if err != nil { log.Logger.Debugf("failed to parse Ubuntu package version: %w", err) continue } if installedVersion.LessThan(fixedVersion) { vulns = append(vulns, vuln) } } } return vulns, nil }
func Get(release string, pkgName string) ([]vulnerability.Advisory, error) { bucket := fmt.Sprintf(platformFormat, release) advisories, err := db.Config{}.ForEach(bucket, pkgName) if err != nil { return nil, xerrors.Errorf("error in Ubuntu foreach: %w", err) } if len(advisories) == 0 { return nil, nil } var results []vulnerability.Advisory for _, v := range advisories { var advisory vulnerability.Advisory if err = json.Unmarshal(v, &advisory); err != nil { return nil, xerrors.Errorf("failed to unmarshal Ubuntu JSON: %w", err) } results = append(results, advisory) } return results, nil }
输出检查结果: func (tw TableWriter) write(result Result) { table := tablewriter.NewWriter(tw.Output) table.SetHeader([]string{"Library", "Vulnerability ID", "Severity", "Installed Version", "Fixed Version", "Title"}) severityCount := map[string]int{} for _, v := range result.Vulnerabilities { severityCount[v.Severity]++ title := v.Title if title == "" { title = v.Description } splittedTitle := strings.Split(title, " ") if len(splittedTitle) >= 12 { title = strings.Join(splittedTitle[:12], " ") + "..." } if tw.Output == os.Stdout { table.Append([]string{v.PkgName, v.VulnerabilityID, vulnerability.ColorizeSeverity(v.Severity), v.InstalledVersion, v.FixedVersion, title}) } else { table.Append([]string{v.PkgName, v.VulnerabilityID, v.Severity, v.InstalledVersion, v.FixedVersion, title}) } } var results []string for _, severity := range vulnerability.SeverityNames { r := fmt.Sprintf("%s: %d", severity, severityCount[severity]) results = append(results, r) } fmt.Printf("\n%s\n", result.FileName) fmt.Println(strings.Repeat("=", len(result.FileName))) fmt.Printf("Total: %d (%s)\n\n", len(result.Vulnerabilities), strings.Join(results, ", ")) if len(result.Vulnerabilities) == 0 { return } table.SetAutoMergeCells(true) table.SetRowLine(true) table.Render() return }
0x02、容器漏洞扫描产品化
主要是让用户提升安全运营效率,快速查找定位,评估容器漏洞危害性,决定是否修复。