引言
Dependency-Check 是一个开源工具,用于检测软件项目中使用的第三方库和组件是否存在已知的安全漏洞。它可以帮助开发团队及时发现和解决项目中的潜在安全风险,从而提高软件的安全性。
该工具通过分析项目的依赖关系,识别其中使用的第三方库和组件,并与已知的漏洞数据库(如 National Vulnerability Database)进行对比,以确定这些依赖项是否受到已知漏洞的影响。一旦发现存在安全漏洞的依赖项,Dependency-Check 将提供详细的报告,包括漏洞描述、影响范围、修复建议等信息,帮助开发者及时采取必要的措施来修复漏洞。
使用 Dependency-Check 工具可以在早期发现并解决项目中的安全问题,减少了软件开发生命周期中安全漏洞带来的风险和成本。它可以集成到持续集成(CI)环境中,实现自动化的安全检测,为软件项目的安全保障提供了可靠的基础。
DependencyCheck项目
Github 项目地址:https://github.com/jeremylong/DependencyCheck
文档地址:https://jeremylong.github.io/DependencyCheck/
使用
注意网络因素
原因不多叙述,漏洞数据库和一些依赖文件会使用到国外网站,例如github等
通过命令
MacOS
1.安装命令
通过Homebrew安装
$ brew install dependency-check
2.执行命令
// 扫描本地的foo-0.0.1-SNAPSHOT.jar文件,报告文件输出到Desktop目录
$ dependency-check --out ~/Desktop/ --scan ./foo-0.0.1-SNAPSHOT.jar
可直接扫描项目用所有的jar目录(libs),或者生成jar文件(springboot)后进行扫描
3.漏洞数据库
Dependency-Check漏洞检测依赖一些数据库文件,如NVD漏洞数据库,首次使用时,需要花费比较长的时间进行下载(视网络条件等因素),界面参考如下:
其次是 RetireJS
,如果下载报错时,例如作者遇到的
Caused by: org.owasp.dependencycheck.utils.DownloadFailedException: Download failed, unable to copy 'https://raw.githubusercontent.com/Retirejs/retire.js/master/repository/jsrepository.json' to '/opt/homebrew/Cellar/dependency-check/9.1.0/libexec/data/jsrepository.json'; Error downloading file https://raw.githubusercontent.com/Retirejs/retire.js/master/repository/jsrepository.json; unable to connect.
at org.owasp.dependencycheck.utils.Downloader.fetchFile(Downloader.java:152)
at org.owasp.dependencycheck.utils.Downloader.fetchFile(Downloader.java:100)
at org.owasp.dependencycheck.data.update.RetireJSDataSource.initializeRetireJsRepo(RetireJSDataSource.java:150)
... 7 common frames omitted
可手动下载 jsrepository.json
文件然后拷贝到本地 /opt/homebrew/Cellar/dependency-check/9.1.0/libexec/data/jsrepository.json
目录即可(根据实际本地提示进行操作)。
其他操作系统
-
到下载页面 https://github.com/jeremylong/DependencyCheck/releases/ 下载最新版本,如
dependency-check-9.1.0-release.zip
-
解压压缩包
-
找到工具目录,如
bin
为命令行工具目录> .bindependency-check.bat -h
> .bindependency-check.bat --out . --scan [path to jar files to be scanned]$ ./bin/dependency-check.sh -h
$ ./bin/dependency-check.sh --out . --scan [path to jar files to be scanned] -
Unix Like系统
-
Windows系统
-
工具依赖,漏洞数据库文件,参见上面MacOS命令,大同小异;
通过Maven插件
全局使用
修改 pom.xml 文件,加入dependency-check插件,参考如下:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!-- dependency-check插件 -->
<plugin>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-maven</artifactId>
<version>9.1.0</version>
<configuration>
<skipProvidedScope>true</skipProvidedScope>
</configuration>
<executions>
<execution>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
生成报告命令
mvn verify -DskipTests
通过命令和通过Maven插件使用的漏洞数据库不共享,所以,又需要下载一遍。
报告结果,会输出到本地(默认是target目录)
具体报告内容查看 dependency-check-report.html
通过Profile灵活使用
由于mvn很多操作,例如install的时候,都会触发 check
动作,所以通过 全局使用 的方式配置的dependency-check插件的情景会比较大,但一般实际项目中我们不需要使用的 那么频繁 。所以,为了更加灵活地生成报告,我们可以把这些配置移动到profile。
pom文件配置参考
<profiles>
<profile>
<id>dev</id>
<!-- 开发环境依赖 -->
<dependencies>
<!-- 引入会被检测出 CVE-2020-26870 漏洞的包 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>3.0.0</version>
</dependency>
</dependencies>
</profile>
<profile>
<id>prod</id>
<dependencies>
<!-- 生产环境依赖 -->
<!-- 可以添加其他生产环境需要的依赖 -->
</dependencies>
</profile>
<profile>
<id>check-report</id>
<build>
<plugins>
<!-- dependency-check插件 -->
<plugin>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-maven</artifactId>
<version>9.1.0</version>
<configuration>
<skipProvidedScope>true</skipProvidedScope>
</configuration>
<executions>
<execution>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
即使用在mvn命令时传入 check-report
时,才会产生dependency-check报告,例如
mvn install -Pprod -Pcheck-report -DskipTests
上述命令同时激活prod和check-report的profile,Maven 将会合并这些 profile 的配置,并将它们一起应用于项目构建过程中。
实践
扫描jar包
查出漏洞
有如下依赖包的项目
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-annotations</artifactId>
<version>${swagger-annotations.version}</version>
</dependency>
<!-- 引入会被检测出 CVE-2020-26870 漏洞的包 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>3.0.0</version>
</dependency>
</dependencies>
生成jar
mvn clean install
编译成功后进行扫描,dependency-check-0.0.1-SNAPSHOT.jar
为作者本地的项目包名
dependency-check --out ~/Desktop/ --scan ./target/dependency-check-0.0.1-SNAPSHOT.jar
扫描结果
分析和解决漏洞
从报告中可以看出有2个漏洞
-
jackson-databind-2.15.4.jar
: 通过Maven Helper
插件分析发现,是从 spring-boot-starter-web:3.2.5 引入进来的。解决办法,引入最新的 jackson-databind
-
springfox-swagger-ui-3.0.0.jar: swagger-ui-bundle.js
: 这个就更加经典了, io.springfox:springfox-swagger-ui:3.0.0 这个包甚至从2020年就不更新了,但依然被人使用在swagger的ui上,而漏洞原因是在包内的js文件。解决办法:
-
使用
springdoc-openapi-ui
代替 springfox-swagger-ui。 -
由于swagger-ui一般使用在开发阶段,实际上我们部署的包并不需要引入,所以,我们可以利用Maven在不同环境生成jar时,过滤掉一些不用的jar包。
最终解决完漏洞的pom文件关键部分
<properties>
<java.version>17</java.version>
<swagger-annotations.version>2.2.21</swagger-annotations.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-annotations</artifactId>
<version>${swagger-annotations.version}</version>
</dependency>
<!-- 解决CVE-2023-35116 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.17.0</version>
</dependency>
</dependencies>
<profiles>
<profile>
<id>dev</id>
<!-- 开发环境依赖 -->
<dependencies>
<!-- 引入会被检测出 CVE-2020-26870 漏洞的包 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>3.0.0</version>
</dependency>
</dependencies>
</profile>
<profile>
<id>prod</id>
<dependencies>
<!-- 生产环境依赖 -->
<!-- 可以添加其他生产环境需要的依赖 -->
</dependencies>
</profile>
</profiles>
dev编译命令
mvn clean install -Pdev -DskipTests
使用 dev 的profile,springfox-swagger-ui
会被继续引入到jar包
dev的报告结果
prod编译命令
mvn clean install -Pprod -DskipTests
其实不指定profile其实也可以,意味着不匹配任何profile内容,也不会加入 springfox-swagger-ui
prod报告结果
设置 NVD API 密钥
初次使用时你可能会看到以下信息
An NVD API Key was not provided - it is highly recommended to use an NVD API key as the update can take a VERY long time without an API Key
这个警告是由于你没有提供 NVD(National Vulnerability Database,国家漏洞数据库)的 API 密钥而引起的。Dependency-Check 在执行漏洞检查时,会使用 NVD 数据库来获取漏洞信息更新。如果你提供了 API 密钥,Dependency-Check 将能够更有效地获取更新的漏洞信息。
警告中指出,如果没有 API 密钥,获取漏洞信息可能会花费很长时间,因为更新的频率受限于 NVD 的公开更新计划。通过提供 API 密钥,你可以更频繁地获取漏洞信息更新,从而减少了等待时间。
虽然没有提供 API 密钥不会阻止 Dependency-Check 的正常运行,但它强烈建议你提供 API 密钥以提高漏洞检查的效率和准确性。
获取密钥
访问 https://nvd.nist.gov/developers/request-an-api-key 填写相关信息
最终,通过邮件,你会收到API密钥
设置密钥
命令的API密钥
$ dependency-check --out ~/Desktop/ --scan ./foo-0.0.1-SNAPSHOT.jar --nvdApiKey <你的API密钥>
使用 --nvdApiKey
参数,指定你的API密钥
Maven插件的API密钥
<plugin>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-maven</artifactId>
<version>9.1.0</version>
<configuration>
<skipProvidedScope>true</skipProvidedScope>
<nvdApiKey>你的API密钥</nvdApiKey>
</configuration>
<executions>
<execution>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
原文始发于微信公众号(晓郎编程):使用DependencyCheck工具检测JAR依赖包的安全漏洞