处理关键的 Log4j 漏洞
在流行的 Apache Log4j 日志库中发现了一个关键的远程代码执行 (RCE) 漏洞,该漏洞影响了 2.0 到 2.14.1(包括)的所有版本。此漏洞影响了大量的基于 JVM 的系统。有关漏洞本身的更多信息,请参阅 CVE-2021-44228。
更新 (2021 年 12 月 22 日):自第一篇博文发布以来,又发现了两个漏洞 - CVE-2021-45046 和 CVE-2021-45105 - 因此请务必查看不同部分以获取更新的说明。
此漏洞正在被积极利用。所有 Gradle 用户都应评估其软件项目是否容易受到攻击,并在必要时尽快更新到 Log4j 2.17.0 或更高版本。我们已 在下面提供了说明,说明如何在您的项目中识别和防止此漏洞。
我们强烈建议您配置您的 Gradle 构建以使用 依赖项约束 拒绝任何易受攻击的 Log4j 版本。
除了您的项目依赖项之外,我们还建议您保护您的构建依赖项,如以下文档所述。
请注意,Gradle 构建工具本身不受此漏洞的影响,因为它不使用 Log4j。Gradle 使用 SLF4J 和一个不受易受攻击的字符串替换影响的自定义日志记录实现。
Gradle Scala 插件 使用 Zinc Scala 编译器,它依赖于易受攻击的 Log4j 版本。但是,在这种情况下,Gradle 还提供自己的日志记录实现,并且默认情况下不使用 Log4j。
此博文的更新
保护您的项目依赖项
1. 确定您的项目是否使用易受攻击的 Log4j 版本
首先,使用 依赖项报告 或 Build Scan™ 验证您的项目是否使用易受攻击的 Log4j 版本。有关详细信息,请参阅 查看和调试依赖项。
所有版本 org.apache.logging.log4j:log4j-core
在 2.0 到 2.16.0(含)之间都是易受攻击的。
2. 将 Log4j 依赖项升级到非易受攻击的版本
升级每个子项目的构建脚本中 dependencies
块中的 Log4j 依赖项,或者如果您使用依赖项的集中声明,则升级您在 版本目录 中的依赖项。
更新 (2021 年 12 月 14 日):Log4j 发布了 2.16.0,它禁用了并删除了对漏洞核心功能的支持。在某些非默认配置中,软件 在 2.15.0 中可能仍然存在漏洞。为了绝对确定,您应该更新到 2.16.0。以下说明已修改为使用 2.16.0。
更新 (2021 年 12 月 22 日):Log4j 发布了 2.17.0,它修复了 另一个漏洞。为了绝对确定,您应该更新到 2.17.0。以下说明已修改为使用 2.17.0。
3. 阻止在您的项目中意外解析易受攻击的 Log4j 版本
鉴于此漏洞的严重性,我们建议您采取以下步骤,以防止意外包含易受攻击的版本。请注意,即使您没有直接使用 Log4j,易受攻击的版本仍然可能通过您的某个依赖项被传递解析。
使用 依赖项约束 功能,通过将以下代码段添加到您的 Gradle 构建中,确保您的项目无法解析受影响的 Log4j 版本。
dependencies {
constraints {
implementation("org.apache.logging.log4j:log4j-core") {
version {
strictly("[2.17, 3[")
prefer("2.17.0")
}
because("CVE-2021-44228, CVE-2021-45046, CVE-2021-45105: Log4j vulnerable to remote code execution and other critical security vulnerabilities")
}
}
}
除非 log4j-core 出现在依赖项图中,否则约束不会被激活。约束将强制将依赖项升级到至少 2.17.0,或者如果无法满足严格的版本约束,则构建将失败。
请注意,在此处使用 implementation
配置将涵盖 Java 库或应用程序的默认设置。但是,如果您有自定义配置或更高级的设置,您还应该将此约束添加到其他配置中。
此外,如果您发布的库定义了此类约束,并使用 Gradle 模块元数据 进行定义,那么任何使用您库的构建在尝试解析易受攻击版本的 log4j-core 时也会失败。
4. 组织范围内的防止使用易受攻击的 Log4j 版本
您的组织可能利用应用于所有项目的共享插件。在这种情况下,您也可以将上述约束应用于组织中的所有项目。
如果您使用 预编译脚本插件,只需将上述 代码段 复制到应用于所有 JVM 项目的脚本中。如果您使用二进制插件,以下是与 DSL 代码段等效的 Java 代码
project.getDependencies().constraints(constraints -> {
constraints.add("implementation", "org.apache.logging.log4j:log4j-core", c -> {
c.version(v -> {
v.strictly("[2.17, 3[");
v.prefer("2.17.0");
});
c.because("CVE-2021-44228, CVE-2021-45046, CVE-2021-45105: Log4j vulnerable to remote code execution and other critical security vulnerabilities");
});
});
保护您的构建依赖项
更新 (2021 年 12 月 15 日):您无需将其应用于 Gradle 7.3.2 及更高版本。Gradle 会自动要求 Log4J 版本为 2.16.0 或更高。
更新 (2021 年 12 月 22 日):您无需将其应用于 Gradle 7.3.3 及更高版本。Gradle 会自动要求 Log4J 版本为 2.17.0 或更高。对于仍在使用 6.x 版本的用户,Gradle 6.9.2 也会这样做。
除了项目依赖项之外,您的项目可能还会使用内部或第三方 Gradle 插件。这些插件也有自己的依赖项,这些依赖项可能会意外地将易受攻击的 Log4j 依赖项引入构建类路径。
换句话说,您的构建逻辑可能与您的生产代码一样容易受到攻击。虽然此类漏洞可能更难利用,但您也可以使用以下代码段来保护您的构建依赖项
buildscript {
dependencies {
constraints {
classpath("org.apache.logging.log4j:log4j-core") {
version {
strictly("[2.17, 3[")
prefer("2.17.0")
}
because("CVE-2021-44228, CVE-2021-45046, CVE-2021-45105: Log4j vulnerable to remote code execution and other critical security vulnerabilities")
}
}
}
}
该代码段应应用于每个构建脚本中的 buildscript
块以及 settings.gradle(.kts) 文件,并确保仅 Log4j 2.17.0 及更高版本可作为构建依赖项解析。该语句必须位于文件顶部。
保护插件门户用户
鉴于最初的 Log4j 漏洞的严重性,Gradle 团队希望改善插件门户用户的状况。我们正在采取措施确保没有新的插件可以依赖易受攻击的 Log4j 版本。以下更改现已可用,并将在以后的更新中强制执行。
作为 Gradle 插件作者,您可能直接或间接依赖易受攻击的 Log4j 版本。为了保护您的插件用户,Gradle 已在其 plugin-publish
插件中添加了新的验证规则。
我们发布了Plugin Publish 插件的 0.19.0 版本,该版本会自动检测易受攻击的 Log4j 插件依赖项,如果发现任何依赖项,则会阻止插件发布并使构建失败。由于 Gradle 运行时不会使用此库进行日志记录,因此通常 Gradle 插件不需要 Log4j,所以没有自动升级。插件作者有责任通过删除依赖项或升级依赖项来解决问题。
在不久的将来,使用此版本的 Plugin Publish 插件将成为强制性的,因为插件门户将拒绝使用旧版本插件完成的任何发布。
Gradle Enterprise 产品
多个 Gradle Enterprise 产品受到 Log4j 漏洞的影响。
Gradle Enterprise、Test Distribution Agent 和 Build Cache Node 的新版本已于 2021 年 12 月 13 日发布。
更新 (2021 年 12 月 22 日):Gradle Enterprise 2021.4 将 Log4j 升级到 2.17.0
反馈
如果您有任何问题,请在我们的论坛或Gradle 社区 Slack上告知我们。