处理关键的 Log4j 漏洞
目录
引言
流行的 Apache Log4j 日志库中发现了一个关键的远程代码执行 (RCE) 漏洞,影响版本 2.0 至 2.14.1(包括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.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 Module Metadata发布带有此类约束的库,那么任何使用您的库的构建如果尝试解析易受攻击的 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 或更高。Gradle 6.9.2 也为仍在使用 6.x 系列的用户执行此操作。
除了项目依赖项,您的项目可能还使用内部或第三方 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
插件中添加了新的验证规则。
我们已经发布了插件发布插件的 0.19.0 版本,该版本会自动检测易受攻击的 Log4j 插件依赖项,如果发现任何此类依赖项,则通过使构建失败来阻止插件发布。没有自动化升级,因为通常 Gradle 插件不需要 Log4j,因为 Gradle 运行时不使用此库进行日志记录。插件作者的职责是通过移除或升级依赖项来解决问题。
在不久的将来,使用此版本的插件发布插件将成为强制要求,插件门户将拒绝使用旧版本插件进行的任何发布。
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上告知我们。