龙空技术网

镜像安全扫描工具Trivy深入实践

神奇的工程师 793

前言:

此时看官们对“mysqlcve扫描工具”大约比较看重,小伙伴们都需要学习一些“mysqlcve扫描工具”的相关内容。那么小编同时在网摘上网罗了一些对于“mysqlcve扫描工具””的相关内容,希望各位老铁们能喜欢,同学们快快来了解一下吧!

随着云原生地快速发展,容器安全和镜像安全日益受到重视。

在镜像安全管控中,已知漏洞风险的扫描发现是非常重要和基础的一个环节。

Trivy 作为该领域的一款优秀和强大的安全扫描工具,已经被不少团队集成和使用。

本文从trivy安装使用出发,重点对 trivy 漏洞库的结构、来源、生成、更新及使用过程进行了分析,以期较好的掌握 trivy 漏洞库的机制。

漏洞扫描能力,特别看重漏洞库本身的质量。漏洞库的信息来源、覆盖类型、更新时间、存储结构都会影响最终的扫描效果。

在此基础上,可以更游刃有余地使用trivy 功能和漏洞库,满足对镜像安全的需求。

概述

项目地址:GitHub - aquasecurity/trivy

最新版本:v0.36.1

官方文档:Overview - Trivy (aquasecurity.github.io)

安装部署

测试环境:腾讯云 CentOS 7.9,没有通用的 Trivy 安装包,无法 yum install。

常见安装方法有三种:

brew install trivy​,适合 MacOS 系统。​docker run aquasec/trivy​,适合 Docker 环境。 下载二进制文件安装,适合其他情况。

省事起见,选择第三种。

$ wget  rpm -ivh trivy_0.36.1_Linux-64bit.rpm

默认可执行程序地址: /usr/local/bin/trivy​。(目测只有这一个可执行文件。)

默认数据存放地址: ~/.cache/trivy​,存储本地漏洞库等数据。

常用命令

trivy [global flags] command [flags] target

trivy [command]

每种扫描能力,对应一种命令:

aws 【实验性】扫描 AWS 账户config 扫描错误配置 Scan config files for misconfigurationsfilesystem 扫描本地文件image 扫描容器镜像。kubernetes 【实验性】扫描 K8s clusterrepository 扫描远程仓库rootfs 扫描 rootfssbom 根据 SBOM 扫描漏洞(可作为简单的 SCA 工具)。vm 【实验性】扫描虚拟机镜像

示例:

# 扫描容器镜像python:3.4-alpine。$ trivy image python:3.4-alpine# 扫描一个tar包的容器镜像ruby-3.1.tar。$ trivy image --input ruby-3.1.tar# 扫描当前目录 $ trivy fs .

扫描容器镜像

最知名的是扫描容器镜像,其命令行用法为:

$ trivy image 镜像名
扫描启动的时候,会检查本地漏洞库。如果超过 12 小时为更新,会自动下载更新漏洞库。由于官方漏洞库放在 github,下载比较慢,可以使用 --skip-db-update​ 跳过这一过程。扫描镜像时,默认会扫描漏洞(vuln)和敏感信息(secret)。如果只关心漏洞风险,使用 --security-checks vuln ​限定为只扫描漏洞。

示例,扫描一个名为 mysql:5.7 的本地 Docker 镜像。

$ trivy image mysql:5.7

扫描之后,以 table 形式展示了该镜像包含的漏洞,提示漏洞所在库(Library)、漏洞编号(Vulnerability)、严重程度(Severity)、当前使用版本(Installed Version)、漏洞修复版本(Fixed Version)以及其他信息(Title)。

例如,该镜像使用的 openssl 库,存在 CVE-2021-23840 ​漏洞。

漏洞库

镜像漏洞库操作(参阅官方文档)

漏洞库下载更新

trivy 提供了一些漏洞库更新的命令。默认情况下 trivy 每次扫描时,都会检查,保证本地漏洞库不超过 12 小时更新。可以使用--skip-db-update 跳过这一过程。

如果希望手工下载更新漏洞库,可以使用如下命令选项。

--download-db-only​ 仅下载漏洞数据库。默认从 ghcr.io/aquasecurity/trivy-db 下载漏洞库。示例:

$ trivy image --download-db-only

注意,trivy 漏洞库目前格式版本为 v2。如果使用早期版本的 trivy,可以到 Releases · aquasecurity/trivy-db (github.com)下载 v1 版本的漏洞库。

--db-repository​ 从指定的 OCI 地址下载漏洞数据库。示例:

$ trivy image --db-repository registry.gitlab.com/gitlab-org/security-products/dependencies/trivy-db

该地址指向由 GitLab 维护的漏洞库 GitLab.org / security-products / dependencies / trivy-db · GitLab 项目。

Trivy 漏洞库是以符合 OCI 制品的方式发布。OCI,Open Container Initialtive,是目前通用的镜像格式规范,以 Docker 镜像规范 v2 为基础制定的,是围绕容器格式和运行时开放的行业标准。它定义了镜像的主要格式及内容,主要用于镜像仓库存放镜像及分发镜像等场景。

因此,除了使用 trivy image --download-db-only ​方式下载漏洞库地址,也可以使用 OCI 制品的通用推拉工具 oras:

oras pull ghcr.io/aquasecurity/trivy-db:2

‍下载下来的漏洞库文件,是一个名为 db.tar.gz ​的压缩包,解压之后包含 metadata.json 和 trivy.db。

trivy 会将这两个文件放到本地 ~/.cache/trivy/db​ 路径下。

本地漏洞库结构

trivy 本地缓存目录为默认 ~/.cache/trivy​。(MACOS 中是 ~/Library/Caches/trivy​)

主要包含内容如下:

metadata.json 是 trivy.db 漏洞库的更新描述文件。

fanal.db、trivy.db 等文件使用 blotDB 数据存储格式。

blotDB,是一个 key-value 形式的数据库,在 go 语言程序中比较常用,可以用 bbolt 等工具查看。

blotDB 数据库的顶层是一个 Bucket 桶列表,桶可以继续嵌套子桶。每个桶里面最终存放的是一组 key-value 的数据集合,大致结构如下:

blotDB文件

* Bucket    * Bucket         * key:value         * key:value    * key:value* Bucket    * key:value* ……

fanal.db

fanal.db ,是容器镜像 ImageID 的快速索引库。trivy 在扫描时可以利用 fanal.db 匹配镜像的 ImageID,快速确认镜像的操作系统、版本等信息。

fanal.db 目前包含两个桶,artifact、blob。artifact 有 3 个 key,blob 有 19 个 key。key 都是使用“sha256:哈希值”形式的 ImageID。

每个 Docker 容器镜像,都有一个“sha256:哈希值”形式地 ImageID 来标识。

$ ./bbolt buckets ~/.cache/trivy/fanal/fanal.db artifactblob

metadata.json

metadata.json 是漏洞库的描述文件,记录了:

Version,漏洞库格式的版本,目前为 2。UpdateAt,本次漏洞库更新时间。(是指漏洞库更新的发布时间,并非本地更新时间)NetxUpdate,下次漏洞库更新时间。(官方库默认每 6 小时更新发布一次)DownloadedAt,漏洞库下载时间。

$ cat .cache/trivy/db/metadata.json{  "Version":2,  "NextUpdate":"2023-01-10T12:06:23.823523551Z",  "UpdatedAt":"2023-01-10T06:06:23.823523951Z",  "DownloadedAt":"2023-01-10T09:03:46.072778518Z"}

如果触发 trivy 更新下载漏洞库过程,trivy 会先删除 metadata.json 文件。此时即便中断更新过程,再次使用--skip-db-update 仍会重新下载漏洞库直到完整更新流程完成,因为检查 metadata.json 已经被删除了。

此问题,可以自己手动按上述格式创建一个 metadata.json 文件来解决。

trivy.db

trivy.db,是漏洞信息的存储库。

trivy.db 有很多存储桶(Bucket)。

大致可以分为如下类型:

以操作系统版本命名的桶,此类占大多数。如"Oracle Linux 7"。

这类桶采用嵌套桶方式,下一次层是以软件名命名的桶,例如“openssl”。

再下一层,就是 key-value 形式的数据了。key 往往以漏洞编号命名,例如“CVE-2021-23840”,value 则是 json 格式字串,记录了针对该操作系统版本软件的具体信息,常见的是 FixedVersion。

下图为 openssl 桶中 key-value 的部分枚举。

vulnerability 桶,1 个。桶内通常以漏洞的 CVE 编号为 key,记录 json 格式的漏洞信息。

data-source 桶,记录了漏洞库的 ID、名称、来源等信息。

下图使用 boltdbweb 呈现。

漏洞库扫描原理

使用 trivy image 扫描镜像的时候,大致步骤包括:

加载漏洞库(默认会检查漏洞库下载时间,并可能先下载更新漏洞库)确认镜像是否在本地,如果不在则拉取镜像。使用漏洞库扫描镜像。

前两步是准备工作,具体来看看第三步的扫描过程。

1)使用 fanal 漏洞库,快速查询操作系统版本信息

trivy 会提取目标镜像的 ImageID,并根据目标镜像记录的生成关系,计算出其基础镜像的 ImageID。

然后,在 fanal.db​​中保存的 ImageID 进行查询。如果命中,就可以快速确基础镜像对应的操作系统、版本信息等信息。

2)解析基础镜像的系统文件,获得操作系统版本信息

如果没有,则需要解析基础镜像,并根据其中的操作系统版本文件(etc/alpine-release、usr/lib/os-release、/etc/os-release 等),来确定基础镜像的操作系统版本。

这种方式,要比查询 fanal.db 慢一些。

示例的 mysql:5.7 的基础镜像 os-release 文件表明,它是一个 Oracle Linux 7 版本的操作系统。

$ sudo cat /var/lib/docker/overlay2/7c2ae603cabf55836770978b28dc133719ce2f43f9c36499308cba1ad080c305/diff/etc/os-releaseNAME="Oracle Linux Server"VERSION="7.9"ID="ol"ID_LIKE="fedora"VARIANT="Server"VARIANT_ID="server"VERSION_ID="7.9"PRETTY_NAME="Oracle Linux Server 7.9"ANSI_COLOR="0;31"CPE_NAME="cpe:/o:oracle:linux:7:9:server"HOME_URL=";BUG_REPORT_URL=";ORACLE_BUGZILLA_PRODUCT="Oracle Linux 7"ORACLE_BUGZILLA_PRODUCT_VERSION=7.9ORACLE_SUPPORT_PRODUCT="Oracle Linux"ORACLE_SUPPORT_PRODUCT_VERSION=7.9

‍3)根据操作系统版本信息,使用不同的检测模块和漏洞库进行检测。

trivy 根据目标基础镜像的操作系统和版本,就可以确定具体的扫描器,在 trivy.db 中使用对应的操作系统版本 Buckets 桶。

trivy 解析目标镜像的文件系统,采集模块和版本信息,并根据模块信息去 trivy.db 中匹配对应模块的漏洞信息。如果找到记录下来,最终形成漏洞检测结果。

例如上文的 mysql:5.7 镜像,在扫描镜像包含的 openssl 库时,会根据操作系统版本,去 trivy.db 的"Oracle Linux 7"、“openssl”桶中查询相关漏洞信息,并最终生成 CVE-2021-23840 漏洞告警。

Trivy 的漏洞库,名叫 trivy-db​​。trivy-db 是以符合 OCI 镜像的方式发布,实际上包含了漏洞管理工具和漏洞库。

Trivy 下载漏洞库,其实就是下载 trivy-db​​的镜像文件。

​trivy-db​​的命令行格式如下:

NAME: trivy-db - Trivy DB builderUSAGE:  main [global options] command [command options] image_nameVERSION:  0.0.1COMMANDS: build build a database fileupload upload database files to GitHub Releasehelp, h Shows a list of commands or help for one commandGLOBAL OPTIONS:--help, -h show help--version, -v print the version

官方漏洞库生成

至此,trivy 的镜像扫描功能、漏洞库更新、以及扫描原理都比较清楚了。

那么,还会由一个好奇,trivy 的漏洞库时怎么来的。

trivy 的代码和漏洞库都放在 github 上维护,可以据此分析一下其官方漏洞库生成过程。

官方漏洞库的生成过程,涉及到这几个项目:

trivy-db:制作 Trivy 漏洞库,并发布。(注意不要和 trivy.db 弄混)早期还有一个 fanal 项目,已经被合并到 trivy-db 项目中。(注意不要和 fanal.db 弄混)vuln-list:存储漏洞信息,并定期发布以 main.tar.gz ​压缩包形式发布。vuln-list-update: 负责收集各个来源的漏洞信息。Trivy 官方使用该工具每天从 NVD, RedHat, Debian, Ubuntu, Alpine 等渠道收集漏洞信息,转换成符合要求的 JSON 格式数据,保存在 vuln-list 项目之中。

通过分析 trivy-db 的 Makefile 文件,可以看出漏洞库更新包的具体生成流程:

首先,trivy-db 会去源头下载漏洞信息库。

1、语言漏洞库,包括 ruby、php 和 node.js,来自各官方项目。具体地址为:

2、vuln-list 漏洞数据库,这也是 trivy 官方维护的漏洞库。具体地址为:

目前,该压缩包大小已经超过 300M。

其次,trivy-db 会将原始压缩包解压、解析、合并,并生成 bboltDB 格式的 trivy.db​ 漏洞库文件,同时生成 metadata.json 文件。

最后,trivy-db 以 OCI 制品的方式将它们打包生成 db.tar.gz ​压缩包,并发布到 ghcr.io/aquasecurity/trivy-db,供 trivy 远程下载。

总结

通过上述分析,基本搞清楚了 trivy 镜像扫描的基本用法和原理。

首先,trivy 收集已知漏洞的渠道还是比较广泛的。trivy 主要针对的是系统和基础组件层的已知漏洞,并在拓展 go、node.js 等平台框架的漏洞。因此,一方面可以省去很多基础系统漏洞层面的关注,另一方面也可以针对自身的需要做加强。

然后,trivy 漏洞库更新比较及时,官方漏洞库每 6 小时更新,本地默认 12 小时更新。trivy 更新包防止在 github 上,每次采用全量更新方式,更新压缩包目前为 30M+。建议在 github 较为通畅的环境下载,并自动同步到内部的 CI/CD 流水线。

最后,trivy 还有很多其他的安全扫描能力,针对包括错误配置、敏感信息等问题。这些也是当下云原生安全中比较关注的安全风险。

参考

harbor+trivy 漏扫实践 - 知乎 (zhihu.com)

用 Trivy 扫描新操作系统的漏洞 - 腾讯云开发者社区-腾讯云 (tencent.com)

超实用的容器镜像漏洞检测工具 Trivy 入门指南 - 腾讯云开发者社区-腾讯云 (tencent.com)

标签: #mysqlcve扫描工具