SBOM扫描

发布时间 2023-07-11 17:09:09作者: 北方姆Q

软件物料清单 (SBOM) 是一个完整的、正式结构化的组件、库和模块列表,这些组件、库和模块是构建(即编译和链接)给定软件以及它们之间的供应链关系所需的。这些组件可以是开源的或专有的,免费的或付费的,可以广泛使用或限制访问。

完成SBOM扫描分为两步

  1. 生成SBOM清单
  2. 基于清单进行安全扫描

预准备

因为trivy也将在后续容器镜像扫描中使用,我们尽量保证技术栈统一,因此第二步会使用trivy扫描SBOM清单
https://github.com/aquasecurity/trivy/releases
https://github.com/aquasecurity/trivy-db

trivy命令的安装是很简单的,下载后解压就能用

# 建议压缩一下,trivy二进制文件还是有点大的,后面使用时会卡
[root@jenkins-bj-ali-ql1 bin]# upx -9q trivy

trivy-db因为一些不可抗力的原因比较复杂,我直接说结果,老实安装oras命令后构建dbv2

# 会非常卡,大概需要下载20分钟后解压tar包
[root@jenkins-bj-ali-ql1 ~]# oras pull ghcr.io/aquasecurity/trivy-db:2
[root@jenkins-bj-ali-ql1 ~]# mkdir -p ~/.cache/trivy/db
[root@jenkins-bj-ali-ql1 ~]# mv trivy.db metadata.json ~/.cache/trivy/db/
切记后续使用跳过db更新!!!这东西更新巨坑,会先删~/.cache/trivy/db/下东西再去拉取,如果拉取不到,那么你库也没了,等于直接用不了了...
建议配置一个定时任务执行oras pull ghcr.io/aquasecurity/trivy-db:2,然后覆盖~/.cache/trivy/db/下内容

生成SBOM清单

  • CycloneDX格式清单
  • SPDX格式清单
  • SWID格式清单
由于trivy sbom仅支持CycloneDX格式,因此我们需要基于CycloneDX生成清单

syft 是一个 CLI 工具和 Go 库,用于从容器镜像和文件系统生成软件物料清单(SBOM)
https://github.com/anchore/syft

与gitleaks一样我们还是clone tidy build upx。后续golang类型命令及压缩安装不再赘述细节

[root@jenkins-bj-ali-ql1]# git clone https://github.com/anchore/syft.git
[root@jenkins-bj-ali-ql1]# go mod tidy
[root@jenkins-bj-ali-ql1]# go build -ldflags '-s -w' cmd/syft/main.go
[root@jenkins-bj-ali-ql1]# mv main syft
[root@jenkins-bj-ali-ql1]# upx -9q syft
[root@jenkins-bj-ali-ql1]# chmod +x syft
[root@jenkins-bj-ali-ql1]# mv syft /usr/local/bin
[root@jenkins-bj-ali-ql1]# syft -h
Generate a packaged-based Software Bill Of Materials (SBOM) from container images and filesystems

Usage:
  syft [SOURCE] [flags]
  syft [command]

Examples:
  syft packages alpine:latest                                a summary of discovered packages
  syft packages alpine:latest -o json                        show all possible cataloging details
  syft packages alpine:latest -o cyclonedx                   show a CycloneDX formatted SBOM
  syft packages alpine:latest -o cyclonedx-json              show a CycloneDX JSON formatted SBOM
  syft packages alpine:latest -o spdx                        show a SPDX 2.3 Tag-Value formatted SBOM
  syft packages alpine:latest -o spdx@2.2                    show a SPDX 2.2 Tag-Value formatted SBOM
  syft packages alpine:latest -o spdx-json                   show a SPDX 2.3 JSON formatted SBOM
  syft packages alpine:latest -o spdx-json@2.2               show a SPDX 2.2 JSON formatted SBOM
  syft packages alpine:latest -vv                            show verbose debug information
  syft packages alpine:latest -o template -t my_format.tmpl  show a SBOM formatted according to given template file

  Supports the following image sources:
    syft packages yourrepo/yourimage:tag     defaults to using images from a Docker daemon. If Docker is not present, the image is pulled directly from the registry.
    syft packages path/to/a/file/or/dir      a Docker tar, OCI tar, OCI directory, SIF container, or generic filesystem directory

  You can also explicitly specify the scheme to use:
    syft packages docker:yourrepo/yourimage:tag            explicitly use the Docker daemon
    syft packages podman:yourrepo/yourimage:tag            explicitly use the Podman daemon
    syft packages registry:yourrepo/yourimage:tag          pull image directly from a registry (no container runtime required)
    syft packages docker-archive:path/to/yourimage.tar     use a tarball from disk for archives created from "docker save"
    syft packages oci-archive:path/to/yourimage.tar        use a tarball from disk for OCI archives (from Skopeo or otherwise)
    syft packages oci-dir:path/to/yourimage                read directly from a path on disk for OCI layout directories (from Skopeo or otherwise)
    syft packages singularity:path/to/yourimage.sif        read directly from a Singularity Image Format (SIF) container on disk
    syft packages dir:path/to/yourproject                  read directly from a path on disk (any directory)
    syft packages file:path/to/yourproject/file            read directly from a path on disk (any single file)

可以看出syft可以帮我们基于镜像、路径生成CycloneDX、SPDX不同格式清单
这时就有一个问题了
如果基于镜像扫描生成清单,在jenkins流水线中应当是放在Package之后,而基于路径咋可以跟gitleaks在一起做并发,对比一下
  • 基于镜像扫描可以将镜像层中的依赖也扫描出来,扫描更加全面
  • 基于路径扫描可以在一开始就检测出问题,不浪费后续资源
还记得我们一开始说的trivy嘛,trivy会在后续过程对镜像层进行专门的扫描工作,因此我们采用路径扫描方式;再者,制品不一定会封装成容器镜像,但是代码一定存在,这样我们的逻辑会更加统一

生成CycloneDX

[root@jenkins-bj-ali-ql1 devops-cicd-dev-bfmq-cloud]# syft packages . -o cyclonedx-json=sbom.json
[root@jenkins-bj-ali-ql1 devops-cicd-dev-bfmq-cloud]# head sbom.json 
{
  "$schema": "http://cyclonedx.org/schema/bom-1.4.schema.json",
  "bomFormat": "CycloneDX",
  "specVersion": "1.4",
  "serialNumber": "urn:uuid:6061b743-f112-48b1-99d0-9c8c70e86ddf",
  "version": 1,
  "metadata": {
    "timestamp": "2023-07-11T16:28:13+08:00",
    "tools": [
      {

基于清单进行安全扫描

直接使用trivy即可,切记要增加--skip-db-update=true!!!

[root@jenkins-bj-ali-ql1 devops-cicd-dev-bfmq-cloud]# trivy sbom sbom.json --skip-db-update=true -s MEDIUM,HIGH,CRITICAL --no-progress
2023-07-11T16:32:19.005+0800	INFO	Vulnerability scanning is enabled
2023-07-11T16:32:19.012+0800	INFO	Detected SBOM format: cyclonedx-json
2023-07-11T16:32:19.029+0800	WARN	Third-party SBOM may lead to inaccurate vulnerability detection
2023-07-11T16:32:19.030+0800	WARN	Recommend using Trivy to generate SBOMs
2023-07-11T16:32:19.032+0800	WARN	Ignore the OS package as no OS information is found.
2023-07-11T16:32:19.044+0800	INFO	Number of language-specific files: 1
2023-07-11T16:32:19.044+0800	INFO	Detecting gobinary vulnerabilities...

 (gobinary)

Total: 1 (MEDIUM: 1, HIGH: 0, CRITICAL: 0)

┌──────────────────────────┬────────────────┬──────────┬───────────────────┬───────────────┬──────────────────────────────────────────────────────┐
│         Library          │ Vulnerability  │ Severity │ Installed Version │ Fixed Version │                        Title                         │
├──────────────────────────┼────────────────┼──────────┼───────────────────┼───────────────┼──────────────────────────────────────────────────────┤
│ github.com/gin-gonic/gin │ CVE-2023-29401 │ MEDIUM   │ v1.9.0            │ 1.9.1         │ The filename parameter of the Context.FileAttachment │
│                          │                │          │                   │               │ function is not p ...                                │
│                          │                │          │                   │               │ https://avd.aquasec.com/nvd/cve-2023-29401           │
└──────────────────────────┴────────────────┴──────────┴───────────────────┴───────────────┴──────────────────────────────────────────────────────┘

集成jenkins pipeline

这次的sbom扫描明显又是基于命令实现的,主逻辑还是使用sh即可完成,但是本次扫描需要分为2步,有依赖关系,现阶段我们以比较基础的方式编写

  1. 我们设计sbom扫描与秘密扫描同样位置
  2. 需要现基于syft生成cyclonedx
  3. 再使用trivy解析清单生成报告
        stage('SBOM') {
            steps {
                script {
                    sh 'syft packages . -o cyclonedx-json=sbom.json -q'
                    def sbomstatus = sh(script: "trivy sbom sbom.json -o sbom.table --exit-code 1 -s MEDIUM,HIGH,CRITICAL --skip-db-update=true -q", returnStatus: true)
                    if (sbomstatus != 0) {
                        sh "cat sbom.table"
                        error "SBOM security scan failed"
                    }
                }
            }
        }

其他sbom扫描工具
Syft
Grype
Trivy
Dependency-check
Dependency-track