当前位置:首页 >探索 >如何检查 Docker 镜像是否存在漏洞 必须尽快修复安全漏洞

如何检查 Docker 镜像是否存在漏洞 必须尽快修复安全漏洞

2024-05-16 07:04:28 [百科] 来源:避面尹邢网

如何检查 Docker 镜像是何检否存在漏洞

作者:科技狠活与软件技术 安全 应用安全 定期检查管道中的漏洞非常重要。要执行的查D存漏步骤之一是对 Docker 映像执行漏洞扫描。在此博客中,像否您将了解如何执行漏洞扫描、何检如何修复漏洞以及如何将其添加到您的查D存漏 Jenkins 管道中。享受!像否

定期检查管道中的何检漏洞非常重要。要执行的查D存漏步骤之一是对 Docker 映像执行漏洞扫描。在此博客中,像否您将了解如何执行漏洞扫描、何检如何修复漏洞以及如何将其添加到您的查D存漏 Jenkins 管道中。

如何检查 Docker 镜像是否存在漏洞 必须尽快修复安全漏洞

1、像否简介

在 几年前的何检一篇博客中,描述了如何扫描 Docker 镜像中的查D存漏漏洞。后续博客展示了如何将扫描添加到 Jenkins 管道。像否 但是, 不再支持以前博客中使用的Anchore Engine 。Anchore也提供了 grype的替代解决方案 。在此博客中,您将更深入地了解 grype、它的工作原理、如何解决问题以及如何将其添加到您的 Jenkins 管道中。

如何检查 Docker 镜像是否存在漏洞 必须尽快修复安全漏洞

但首先,为什么要检查漏洞?您必须及时了解最新的安全修复程序。许多安全漏洞是 公开的因此很容易被利用。因此,必须尽快修复安全漏洞,以最大限度地减少攻击面。但是如何跟上这个呢?您主要专注于业务,不想全职从事修复安全漏洞的工作。这就是为什么自动扫描您的应用程序和 Docker 镜像很重要。Grype 可以帮助扫描您的 Docker 镜像。Grype 将检查操作系统漏洞以及特定语言包(如 Java jar 文件)的漏洞并报告它们。这样,您就有了一个很棒的工具,可以为您自动执行安全检查。请注意,grype 不仅限于扫描 Docker 图像。它还可以扫描文件和目录,因此可用于扫描您的源代码。

如何检查 Docker 镜像是否存在漏洞 必须尽快修复安全漏洞

在此博客中,您将创建一个包含 Spring Boot 应用程序的易受攻击的 Docker 映像。您将安装并使用 grype 以扫描图像并修复漏洞。最后,您将学习如何将扫描添加到您的 Jenkins 管道中。

本博客中使用的资源可以在 GitHub 上找到。

2.先决条件

此博客所需的先决条件是:

  • 基本的Linux知识;
  • 基本的 Docker 知识;
  • 基本的 Java 和 Spring Boot 知识。

3.易受攻击的应用程序

导航到Spring Initializr并选择 Maven 构建、Java 17、Spring Boot 2.7.6 和 Spring Web 依赖项。这不会是一个非常脆弱的应用程序,因为 Spring 已经确保您使用最新的 Spring Boot 版本。因此,将Spring Boot版本改为2.7.0。可以使用以下命令构建 Spring Boot 应用程序,该命令将为您创建 jar 文件:

$ mvn clean verify

您将扫描一个 Docker 镜像,因此需要创建一个 Dockerfile。您将使用一个非常基本的 Dockerfile,它只包含创建图像所需的最少指令。如果您想创建生产就绪的 Docker 映像,请阅读文章Docker 最佳实践和Spring Boot Docker 最佳实践。

FROM eclipse-temurin:17.0.1_12-jre-alpine
WORKDIR /opt/app
ARG JAR_FILE
COPY target/${ JAR_FILE} app.jar

ENTRYPOINT ["java", "-jar", "app.jar"]在撰写本文时,Java 17 的最新 eclipse-temurin基础映像是版本 17.0.5_8。同样,使用旧版本以使其易受攻击。

dockerfile-maven-plugin为了构建 Docker 镜像,将使用 Spotify的一个分支。因此,将以下片段添加到pom文件中。

<plugin>
<groupId>com.xenoamess.docker</groupId>
<artifactId>dockerfile-maven-plugin</artifactId>
<version>1.4.25</version>
<configuration>
<repository>mydeveloperplanet/mygrypeplanet</repository>
<tag>${ project.version}</tag>
<buildArgs>
<JAR_FILE>${ project.build.finalName}.jar</JAR_FILE>
</buildArgs>
</configuration>
</plugin>

使用此插件的好处是您可以轻松地重用配置。可以通过单个 Maven 命令创建 Docker 映像。

可以通过调用以下命令来构建 Docker 映像:

$ mvn dockerfile:build

您现在已经准备好开始使用 grype。

4、安装

可以通过执行以下脚本来安装 grype:

$ curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin​

通过执行以下命令验证安装:

$ grype version
Application: grype
Version: 0.54.0
Syft Version: v0.63.0
BuildDate: 2022-12-13T15:02:51Z
GitCommit: 93499eec7e3ce2704755e9f51457181b06b519c5
GitDescription: v0.54.0
Platform: linux/amd64
GoVersion: go1.18.8
Compiler: gc
Supported DB Schema: 5

5.扫描镜像

扫描 Docker 镜像是通过调用grype后跟 来完成的docker:,表明你想扫描来自 Docker 守护进程的镜像,镜像和标签:

$ grype docker:mydeveloperplanet/mygrypeplanet:0.0.1-SNAPSHOT
Application: grype
Version: 0.54.0
Syft Version: v0.63.0
Vulnerability DB [updated]
Loaded image
Parsed image
Cataloged packages [50 packages]
Scanned image [42 vulnerabilities]
NAME INSTALLED FIXED-IN TYPE VULNERABILITY SEVERITY
busybox 1.34.1-r3 1.34.1-r5 apk CVE-2022-28391 High
jackson-databind 2.13.3 java-archive CVE-2022-42003 High
jackson-databind 2.13.3 java-archive CVE-2022-42004 High
jackson-databind 2.13.3 2.13.4 java-archive GHSA-rgv9-q543-rqg4 High
jackson-databind 2.13.3 2.13.4.1 java-archive GHSA-jjjh-jjxp-wpff High
java 17.0.1+12 binary CVE-2022-21248 Low
java 17.0.1+12 binary CVE-2022-21277 Medium
java 17.0.1+12 binary CVE-2022-21282 Medium
java 17.0.1+12 binary CVE-2022-21283 Medium
java 17.0.1+12 binary CVE-2022-21291 Medium
java 17.0.1+12 binary CVE-2022-21293 Medium
java 17.0.1+12 binary CVE-2022-21294 Medium
java 17.0.1+12 binary CVE-2022-21296 Medium
java 17.0.1+12 binary CVE-2022-21299 Medium
java 17.0.1+12 binary CVE-2022-21305 Medium
java 17.0.1+12 binary CVE-2022-21340 Medium
java 17.0.1+12 binary CVE-2022-21341 Medium
java 17.0.1+12 binary CVE-2022-21360 Medium
java 17.0.1+12 binary CVE-2022-21365 Medium
java 17.0.1+12 binary CVE-2022-21366 Medium
libcrypto1.1 1.1.1l-r7 apk CVE-2021-4160 Medium
libcrypto1.1 1.1.1l-r7 1.1.1n-r0 apk CVE-2022-0778 High
libcrypto1.1 1.1.1l-r7 1.1.1q-r0 apk CVE-2022-2097 Medium
libretls 3.3.4-r2 3.3.4-r3 apk CVE-2022-0778 High
libssl1.1 1.1.1l-r7 apk CVE-2021-4160 Medium
libssl1.1 1.1.1l-r7 1.1.1n-r0 apk CVE-2022-0778 High
libssl1.1 1.1.1l-r7 1.1.1q-r0 apk CVE-2022-2097 Medium
snakeyaml 1.30 java-archive GHSA-mjmj-j48q-9wg2 High
snakeyaml 1.30 1.31 java-archive GHSA-3mc7-4q67-w48m High
snakeyaml 1.30 1.31 java-archive GHSA-98wm-3w3q-mw94 Medium
snakeyaml 1.30 1.31 java-archive GHSA-c4r9-r8fh-9vj2 Medium
snakeyaml 1.30 1.31 java-archive GHSA-hhhw-99gj-p3c3 Medium
snakeyaml 1.30 1.32 java-archive GHSA-9w3m-gqgf-c4p9 Medium
snakeyaml 1.30 1.32 java-archive GHSA-w37g-rhq8-7m4j Medium
spring-core 5.3.20 java-archive CVE-2016-1000027 Critical
ssl_client 1.34.1-r3 1.34.1-r5 apk CVE-2022-28391 High
zlib 1.2.11-r3 1.2.12-r0 apk CVE-2018-25032 High
zlib 1.2.11-r3 1.2.12-r2 apk CVE-2022-37434 Critical

这个输出告诉你什么?

  • NAME:易受攻击包的名称;
  • INSTALLED:安装了哪个版本;
  • FIXED-IN:漏洞修复在哪个版本;
  • TYPE:依赖的类型,例如 JDK 的二进制等;
  • 漏洞;漏洞的标识符。使用此标识符,您可以获得有关 CVE 数据库中漏洞的更多信息;
  • 严重性:不言而喻,可以是可忽略的、低的、中等的、高的、严重的之一。

当您仔细查看输出时,您会注意到并非每个漏洞都有已确认的修复。那么在这种情况下该怎么办?Grype 提供了一个选项,以便仅显示已确认修复的漏洞。添加--only-fixed标志就可以了。

$ grype docker:mydeveloperplanet/mygrypeplanet:0.0.1-SNAPSHOT --only-fixed
Vulnerability DB [no update available]
Loaded image
Parsed image
Cataloged packages [50 packages]
Scanned image [42 vulnerabilities]

NAME INSTALLED FIXED-IN TYPE VULNERABILITY SEVERITY
busybox 1.34.1-r3 1.34.1-r5 apk CVE-2022-28391 High
jackson-databind 2.13.3 2.13.4 java-archive GHSA-rgv9-q543-rqg4 High
jackson-databind 2.13.3 2.13.4.1 java-archive GHSA-jjjh-jjxp-wpff High
libcrypto1.1 1.1.1l-r7 1.1.1n-r0 apk CVE-2022-0778 High
libcrypto1.1 1.1.1l-r7 1.1.1q-r0 apk CVE-2022-2097 Medium
libretls 3.3.4-r2 3.3.4-r3 apk CVE-2022-0778 High
libssl1.1 1.1.1l-r7 1.1.1n-r0 apk CVE-2022-0778 High
libssl1.1 1.1.1l-r7 1.1.1q-r0 apk CVE-2022-2097 Medium
snakeyaml 1.30 1.31 java-archive GHSA-3mc7-4q67-w48m High
snakeyaml 1.30 1.31 java-archive GHSA-98wm-3w3q-mw94 Medium
snakeyaml 1.30 1.31 java-archive GHSA-c4r9-r8fh-9vj2 Medium
snakeyaml 1.30 1.31 java-archive GHSA-hhhw-99gj-p3c3 Medium
snakeyaml 1.30 1.32 java-archive GHSA-9w3m-gqgf-c4p9 Medium
snakeyaml 1.30 1.32 java-archive GHSA-w37g-rhq8-7m4j Medium
ssl_client 1.34.1-r3 1.34.1-r5 apk CVE-2022-28391 High
zlib 1.2.11-r3 1.2.12-r0 apk CVE-2018-25032 Highzlib 1.2.11-r3 1.2.12-r2 apk CVE-2022-37434 Critical

请注意,尽管 Java 17 JDK 存在更新的更新,但 Java JDK 的漏洞已消失。然而,这可能不是什么大问题,因为其他(非 java-archive)漏洞向您显示基本映像已过时。

6.修复漏洞

在这种情况下,修复漏洞非常容易。首先,您需要更新 Docker 基础映像。更改 Docker 镜像中的第一行:

FROM eclipse-temurin:17.0.1_12-jre-alpine

进入:

FROM eclipse-temurin:17.0.5_8-jre-alpine

构建镜像并再次运行扫描:

$ mvn dockerfile:build
...
$ grype docker:mydeveloperplanet/mygrypeplanet:0.0.1-SNAPSHOT --only-fixed
Vulnerability DB [no update available]
Loaded image
Parsed image
Cataloged packages [62 packages]
Scanned image [14 vulnerabilities]
NAME INSTALLED FIXED-IN TYPE VULNERABILITY SEVERITY
jackson-databind 2.13.3 2.13.4 java-archive GHSA-rgv9-q543-rqg4 High
jackson-databind 2.13.3 2.13.4.1 java-archive GHSA-jjjh-jjxp-wpff High
snakeyaml 1.30 1.31 java-archive GHSA-3mc7-4q67-w48m High
snakeyaml 1.30 1.31 java-archive GHSA-98wm-3w3q-mw94 Medium
snakeyaml 1.30 1.31 java-archive GHSA-c4r9-r8fh-9vj2 Medium
snakeyaml 1.30 1.31 java-archive GHSA-hhhw-99gj-p3c3 Medium
snakeyaml 1.30 1.32 java-archive GHSA-9w3m-gqgf-c4p9 Medium
snakeyaml 1.30 1.32 java-archive GHSA-w37g-rhq8-7m4j Medium

正如您在输出中看到的,只有 java-archive 漏洞仍然存在。其他漏洞已经解决。

接下来修复Spring Boot依赖漏洞。在 pom.xml 中将 Spring Boot 的版本从 2.7.0 更改为 2.7.6。

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.6</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>

构建 jar 文件,构建 Docker 镜像并再次运行扫描:

$ mvn clean verify
...
$ mvn dockerfile:build
...
$ grype docker:mydeveloperplanet/mygrypeplanet:0.0.1-SNAPSHOT --only-fixed
Vulnerability DB [no update available]
Loaded image
Parsed image
Cataloged packages [62 packages]
Scanned image [10 vulnerabilities]
NAME INSTALLED FIXED-IN TYPE VULNERABILITY SEVERITY
snakeyaml 1.30 1.31 java-archive GHSA-3mc7-4q67-w48m High
snakeyaml 1.30 1.31 java-archive GHSA-98wm-3w3q-mw94 Medium
snakeyaml 1.30 1.31 java-archive GHSA-c4r9-r8fh-9vj2 Medium
snakeyaml 1.30 1.31 java-archive GHSA-hhhw-99gj-p3c3 Medium
snakeyaml 1.30 1.32 java-archive GHSA-9w3m-gqgf-c4p9 Medium
snakeyaml 1.30 1.32 java-archive GHSA-w37g-rhq8-7m4j Medium

因此,您摆脱了jackson-databind漏洞,但没有摆脱snakeyaml漏洞。那么,在哪个依赖项中使用了 snakeyaml 1.30?你可以通过dependency:treeMaven命令找到。为简洁起见,此处仅显示部分输出:

$ mvnd dependency:tree
...
com.mydeveloperplanet:mygrypeplanet:jar:0.0.1-SNAPSHOT
[INFO] +- org.springframework.boot:spring-boot-starter-web:jar:2.7.6:compile
[INFO] | +- org.springframework.boot:spring-boot-starter:jar:2.7.6:compile
[INFO] | | +- org.springframework.boot:spring-boot:jar:2.7.6:compile
[INFO] | | +- org.springframework.boot:spring-boot-autoconfigure:jar:2.7.6:compile
[INFO] | | +- org.springframework.boot:spring-boot-starter-logging:jar:2.7.6:compile
[INFO] | | | +- ch.qos.logback:logback-classic:jar:1.2.11:compile
[INFO] | | | | \- ch.qos.logback:logback-core:jar:1.2.11:compile
[INFO] | | | +- org.apache.logging.log4j:log4j-to-slf4j:jar:2.17.2:compile
[INFO] | | | | \- org.apache.logging.log4j:log4j-api:jar:2.17.2:compile
[INFO] | | | \- org.slf4j:jul-to-slf4j:jar:1.7.36:compile
[INFO] | | +- jakarta.annotation:jakarta.annotation-api:jar:1.3.5:compile
[INFO] | | \- org.yaml:snakeyaml:jar:1.30:compile

输出告诉我们依赖是依赖的一部分 spring-boot-starter-web。那么,如何解决这个问题呢?严格来说Spring要解决的。但如果你不想等待解决方案,你可以自己解决。

解决方案 1:您不需要依赖项。这是最简单的修复和低风险。只需从 pom.xml 中的依赖项中排除依赖spring-boot-starter-web项即可。

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
</exclusion>
</exclusions>
</dependency>

构建 jar 文件,构建 Docker 镜像并再次运行扫描:

$ mvn clean verify
...
$ mvn dockerfile:build
...
$ grype docker:mydeveloperplanet/mygrypeplanet:0.0.1-SNAPSHOT --only-fixed
Vulnerability DB [no update available]
Loaded image
Parsed image
Cataloged packages [61 packages]
Scanned image [3 vulnerabilities]
No vulnerabilities found

没有发现漏洞了。

解决方案 2:您确实需要依赖项。您可以通过dependencyManagement在 pom.xml 中替换此传递依赖项。这有点棘手,因为更新的传递依赖没有用spring-boot-starter-web依赖进行测试。是否要这样做是一种权衡。将以下部分添加到 pom:

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.32</version>
</dependency>
</dependencies>
</dependencyManagement>

构建 jar 文件,构建 Docker 镜像并再次运行扫描:

$ mvn clean verify
...
$ mvn dockerfile:build
...
$ grype docker:mydeveloperplanet/mygrypeplanet:0.0.1-SNAPSHOT --only-fixed
Vulnerability DB [no update available]
Loaded image
Parsed image
Cataloged packages [62 packages]
Scanned image [3 vulnerabilities]
No vulnerabilities found

同样,不再存在漏洞。

解决方案 3:当您不想做任何事情或它是否是误报通知时,这是解决方案。创建一个 .grype.yaml文件,您可以在其中排除高严重性的漏洞,并使用 --config标志执行扫描,后跟 .grype.yaml包含排除项的文件。

该.grype.yaml文件如下所示:

ignore:
- vulnerability: GHSA-3mc7-4q67-w48m

再次运行扫描:

$ grype docker:mydeveloperplanet/mygrypeplanet:0.0.1-SNAPSHOT --only-fixed
Vulnerability DB [no update available]
Loaded image
Parsed image
Cataloged packages [62 packages]
Scanned image [10 vulnerabilities]
NAME INSTALLED FIXED-IN TYPE VULNERABILITY SEVERITY
snakeyaml 1.30 1.31 java-archive GHSA-98wm-3w3q-mw94 Medium
snakeyaml 1.30 1.31 java-archive GHSA-c4r9-r8fh-9vj2 Medium
snakeyaml 1.30 1.31 java-archive GHSA-hhhw-99gj-p3c3 Medium
snakeyaml 1.30 1.32 java-archive GHSA-9w3m-gqgf-c4p9 Medium
snakeyaml 1.30 1.32 java-archive GHSA-w37g-rhq8-7m4j Medium

不再显示高漏洞。

7. 持续集成

现在您知道如何手动扫描 Docker 镜像了。但是,您可能希望将扫描图像作为持续集成管道的一部分。本节给出了使用Jenkins作为CI平台时的解决方案。

第一个要回答的问题是当发现漏洞时如何通知您?到目前为止,您只能通过查看标准输出来注意到漏洞。这不是 CI 管道的解决方案。你想得到通知,这可以通过构建失败来完成。Grype 有用 --fail-on <severity>于此目的的标志。negligible当发现具有严重性的漏洞时,您可能不希望管道失败 。

让我们看看当您手动执行此操作时会发生什么。首先再次介绍一下Spring Boot应用和Docker镜像中的漏洞。

构建 jar 文件,构建 Docker 镜像并使用标志运行扫描--fail-on:

$ mvn clean verify
...
$ mvn dockerfile:build
...
$ grype docker:mydeveloperplanet/mygrypeplanet:0.0.1-SNAPSHOT --only-fixed --fail-on high
...
1 error occurred:
* discovered vulnerabilities at or above the severity threshold

此处并未显示所有输出,仅显示重要部分。而且,如您所见,在输出的末尾,会显示一条消息,表明扫描产生了错误。这将导致您的 Jenkins 管道失败,并因此通知开发人员出现问题。

为了将其添加到您的 Jenkins 管道中,存在多种选择。这里选择创建 Docker 镜像并从 Maven 中执行 grype Docker 扫描。grype 没有单独的 Maven 插件,但您可以为此目的使用exec-maven-plugin 。将以下内容添加到 pom.xml 的构建插件部分。

<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<executable>grype</executable>
<arguments>
<argument>docker:mydeveloperplanet/mygrypeplanet:${ project.version}</argument>
<argument>--scope</argument>
<argument>all-layers</argument>
<argument>--fail-on</argument>
<argument>high</argument>
<argument>--only-fixed</argument>
<argument>-q</argument>
</arguments>
</configuration>
</plugin>
</plugins>
</build>

这里添加了两个额外的标志:

  • --scope all-layers:这将扫描 Docker 镜像中涉及的所有层;
  • -q:这将使用安静的日志记录,并且只会显示漏洞和可能的故障。

您可以使用以下命令调用它:

$ mvnd exec:exec

您可以将其添加到 withMaven 包装器内的 Jenkinsfile 中:

withMaven() { 
sh 'mvn dockerfile:build dockerfile:push exec:exec'
}

八、结论

在这篇博客中,您学习了如何使用 grype 扫描 Docker 镜像。Grype 有一些有趣的、用户友好的特性,可以让你有效地将它们添加到你的 Jenkins 管道中。此外,安装 grype 非常简单。Grype 绝对是对 Anchor Engine 的巨大改进。

责任编辑:华轩 来源: 今日头条 漏洞Docker安全

(责任编辑:探索)

    推荐文章
    热点阅读