您现在的位置是:电脑教程 >>正文

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

电脑教程29人已围观

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

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

1 、像否简介

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

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

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

复制FROM eclipse-temurin:17.0.1_12-jre-alpineWORKDIR /opt/appARG JAR_FILECOPY target/${ JAR_FILE} app.jar1.2.3.4.

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>1.2.3.4.5.6.7.8.9.10.11.12.

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

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

复制$ mvn dockerfile:build1.

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

4、安装

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

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

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

复制$ grype versionApplication: grypeVersion: 0.54.0Syft Version: v0.63.0BuildDate: 2022-12-13T15:02:51ZGitCommit: 93499eec7e3ce2704755e9f51457181b06b519c5GitDescription: v0.54.0Platform: linux/amd64GoVersion: go1.18.8Compiler: gcSupported DB Schema: 51.2.3.4.5.6.7.8.9.10.11. 5.扫描镜像

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

复制$ grype docker:mydeveloperplanet/mygrypeplanet:0.0.1-SNAPSHOTApplication: grypeVersion: 0.54.0Syft Version: v0.63.0Vulnerability DB [updated

]

Loaded imageParsed imageCataloged packages [50 packages

]

Scanned image [42 vulnerabilities

]

NAME INSTALLED FIXED-IN TYPE VULNERABILITY SEVERITYbusybox 1.34.1-r3 1.34.1-r5 apk CVE-2022-28391 Highjackson-databind 2.13.3 java-archive CVE-2022-42003 Highjackson-databind 2.13.3 java-archive CVE-2022-42004 Highjackson-databind 2.13.3 2.13.4 java-archive GHSA-rgv9-q543-rqg4 Highjackson-databind 2.13.3 2.13.4.1 java-archive GHSA-jjjh-jjxp-wpff Highjava 17.0.1+12 binary CVE-2022-21248 Lowjava 17.0.1+12 binary CVE-2022-21277 Mediumjava 17.0.1+12 binary CVE-2022-21282 Mediumjava 17.0.1+12 binary CVE-2022-21283 Mediumjava 17.0.1+12 binary CVE-2022-21291 Mediumjava 17.0.1+12 binary CVE-2022-21293 Mediumjava 17.0.1+12 binary CVE-2022-21294 Mediumjava 17.0.1+12 binary CVE-2022-21296 Mediumjava 17.0.1+12 binary CVE-2022-21299 Mediumjava 17.0.1+12 binary CVE-2022-21305 Mediumjava 17.0.1+12 binary CVE-2022-21340 Mediumjava 17.0.1+12 binary CVE-2022-21341 Mediumjava 17.0.1+12 binary CVE-2022-21360 Mediumjava 17.0.1+12 binary CVE-2022-21365 Mediumjava 17.0.1+12 binary CVE-2022-21366 Mediumlibcrypto1.1 1.1.1l-r7 apk CVE-2021-4160 Mediumlibcrypto1.1 1.1.1l-r7 1.1.1n-r0 apk CVE-2022-0778 Highlibcrypto1.1 1.1.1l-r7 1.1.1q-r0 apk CVE-2022-2097 Mediumlibretls 3.3.4-r2 3.3.4-r3 apk CVE-2022-0778 Highlibssl1.1 1.1.1l-r7 apk CVE-2021-4160 Mediumlibssl1.1 1.1.1l-r7 1.1.1n-r0 apk CVE-2022-0778 Highlibssl1.1 1.1.1l-r7 1.1.1q-r0 apk CVE-2022-2097 Mediumsnakeyaml 1.30 java-archive GHSA-mjmj-j48q-9wg2 Highsnakeyaml 1.30 1.31 java-archive GHSA-3mc7-4q67-w48m Highsnakeyaml 1.30 1.31 java-archive GHSA-98wm-3w3q-mw94 Mediumsnakeyaml 1.30 1.31 java-archive GHSA-c4r9-r8fh-9vj2 Mediumsnakeyaml 1.30 1.31 java-archive GHSA-hhhw-99gj-p3c3 Mediumsnakeyaml 1.30 1.32 java-archive GHSA-9w3m-gqgf-c4p9 Mediumsnakeyaml 1.30 1.32 java-archive GHSA-w37g-rhq8-7m4j Mediumspring-core 5.3.20 java-archive CVE-2016-1000027 Criticalssl_client 1.34.1-r3 1.34.1-r5 apk CVE-2022-28391 Highzlib 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 Critical1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.30.31.32.33.34.35.36.37.38.39.40.41.42.43.44.45.46.47.48.

这个输出告诉你什么 ?

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

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

复制$ grype docker:mydeveloperplanet/mygrypeplanet:0.0.1-SNAPSHOT --only-fixedVulnerability DB [no update available

]

Loaded imageParsed imageCataloged packages [50 packages

]

Scanned image [42 vulnerabilities

]

NAME INSTALLED FIXED-IN TYPE VULNERABILITY SEVERITYbusybox 1.34.1-r3 1.34.1-r5 apk CVE-2022-28391 Highjackson-databind 2.13.3 2.13.4 java-archive GHSA-rgv9-q543-rqg4 Highjackson-databind 2.13.3 2.13.4.1 java-archive GHSA-jjjh-jjxp-wpff Highlibcrypto1.1 1.1.1l-r7 1.1.1n-r0 apk CVE-2022-0778 Highlibcrypto1.1 1.1.1l-r7 1.1.1q-r0 apk CVE-2022-2097 Mediumlibretls 3.3.4-r2 3.3.4-r3 apk CVE-2022-0778 Highlibssl1.1 1.1.1l-r7 1.1.1n-r0 apk CVE-2022-0778 Highlibssl1.1 1.1.1l-r7 1.1.1q-r0 apk CVE-2022-2097 Mediumsnakeyaml 1.30 1.31 java-archive GHSA-3mc7-4q67-w48m Highsnakeyaml 1.30 1.31 java-archive GHSA-98wm-3w3q-mw94 Mediumsnakeyaml 1.30 1.31 java-archive GHSA-c4r9-r8fh-9vj2 Mediumsnakeyaml 1.30 1.31 java-archive GHSA-hhhw-99gj-p3c3 Mediumsnakeyaml 1.30 1.32 java-archive GHSA-9w3m-gqgf-c4p9 Mediumsnakeyaml 1.30 1.32 java-archive GHSA-w37g-rhq8-7m4j Mediumssl_client 1.34.1-r3 1.34.1-r5 apk CVE-2022-28391 Highzlib 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 Critical1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.

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

6.修复漏洞

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

复制FROM eclipse-temurin:17.0.1_12-jre-alpine1.

进入 :

复制FROM eclipse-temurin:17.0.5_8-jre-alpine1.

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

复制$ mvn dockerfile:build...$ grype docker:mydeveloperplanet/mygrypeplanet:0.0.1-SNAPSHOT --only-fixedVulnerability DB [no update available

]

Loaded imageParsed imageCataloged packages [62 packages

]

Scanned image [14 vulnerabilities

]

NAME INSTALLED FIXED-IN TYPE VULNERABILITY SEVERITYjackson-databind 2.13.3 2.13.4 java-archive GHSA-rgv9-q543-rqg4 Highjackson-databind 2.13.3 2.13.4.1 java-archive GHSA-jjjh-jjxp-wpff Highsnakeyaml 1.30 1.31 java-archive GHSA-3mc7-4q67-w48m Highsnakeyaml 1.30 1.31 java-archive GHSA-98wm-3w3q-mw94 Mediumsnakeyaml 1.30 1.31 java-archive GHSA-c4r9-r8fh-9vj2 Mediumsnakeyaml 1.30 1.31 java-archive GHSA-hhhw-99gj-p3c3 Mediumsnakeyaml 1.30 1.32 java-archive GHSA-9w3m-gqgf-c4p9 Mediumsnakeyaml 1.30 1.32 java-archive GHSA-w37g-rhq8-7m4j Medium1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.

正如您在输出中看到的,只有 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>1.2.3.4.5.6.

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

复制$ mvn clean verify...$ mvn dockerfile:build...$ grype docker:mydeveloperplanet/mygrypeplanet:0.0.1-SNAPSHOT --only-fixedVulnerability DB [no update available

]

Loaded imageParsed imageCataloged packages [62 packages

]

Scanned image [10 vulnerabilities

]

NAME INSTALLED FIXED-IN TYPE VULNERABILITY SEVERITYsnakeyaml 1.30 1.31 java-archive GHSA-3mc7-4q67-w48m Highsnakeyaml 1.30 1.31 java-archive GHSA-98wm-3w3q-mw94 Mediumsnakeyaml 1.30 1.31 java-archive GHSA-c4r9-r8fh-9vj2 Mediumsnakeyaml 1.30 1.31 java-archive GHSA-hhhw-99gj-p3c3 Mediumsnakeyaml 1.30 1.32 java-archive GHSA-9w3m-gqgf-c4p9 Mediumsnakeyaml 1.30 1.32 java-archive GHSA-w37g-rhq8-7m4j Medium1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.

因此,您摆脱了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:compile1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.

输出告诉我们依赖是依赖的一部分 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>1.2.3.4.5.6.7.8.9.10.

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

复制$ mvn clean verify...$ mvn dockerfile:build...$ grype docker:mydeveloperplanet/mygrypeplanet:0.0.1-SNAPSHOT --only-fixedVulnerability DB [no update available

]

Loaded imageParsed imageCataloged packages [61 packages

]

Scanned image [3 vulnerabilities

]

No vulnerabilities found1.2.3.4.5.6.7.8.9.10.11.

没有发现漏洞了 。

解决方案 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>1.2.3.4.5.6.7.8.9.

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

复制$ mvn clean verify...$ mvn dockerfile:build...$ grype docker:mydeveloperplanet/mygrypeplanet:0.0.1-SNAPSHOT --only-fixedVulnerability DB [no update available

]

Loaded imageParsed imageCataloged packages [62 packages

]

Scanned image [3 vulnerabilities

]

No vulnerabilities found1.2.3.4.5.6.7.8.9.10.11.

同样 ,不再存在漏洞。

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

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

复制ignore

:

- vulnerability: GHSA-3mc7-4q67-w48m1.2.

再次运行扫描 :

复制$ grype docker:mydeveloperplanet/mygrypeplanet:0.0.1-SNAPSHOT --only-fixedVulnerability DB [no update available

]

Loaded imageParsed imageCataloged packages [62 packages

]

Scanned image [10 vulnerabilities

]

NAME INSTALLED FIXED-IN TYPE VULNERABILITY SEVERITYsnakeyaml 1.30 1.31 java-archive GHSA-98wm-3w3q-mw94 Mediumsnakeyaml 1.30 1.31 java-archive GHSA-c4r9-r8fh-9vj2 Mediumsnakeyaml 1.30 1.31 java-archive GHSA-hhhw-99gj-p3c3 Mediumsnakeyaml 1.30 1.32 java-archive GHSA-9w3m-gqgf-c4p9 Mediumsnakeyaml 1.30 1.32 java-archive GHSA-w37g-rhq8-7m4j Medium1.2.3.4.5.6.7.8.9.10.11.12.

不再显示高漏洞。

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 threshold1.2.3.4.5.6.7.8.

此处并未显示所有输出,仅显示重要部分。而且,如您所见,在输出的末尾 ,会显示一条消息,表明扫描产生了错误 。这将导致您的 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>1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.

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

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

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

复制$ mvnd exec:exec1.

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

复制withMaven

() {

sh mvn dockerfile:build dockerfile:push exec:exec }1.2.3. 八、结论

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

Tags:

相关文章


滇ICP备2023000592号-18