1. 描述
在 Apache Log4j2 版本(最高包括 2.14.1)(不包括安全发布版 2.3.1、2.12.2 和 2.12.3)中,在配置、日志消息和参数中使用的 JNDI 功能部件不能抵御攻击者控制的 LDAP 和其他 JNDI 相关的端点的攻击。启用消息查找替换后,能够控制日志消息或日志消息参数的攻击者可以执行从 LDAP 服务器加载的任意代码。从 2.0-beta9 到 2.14.1 的所有版本皆收到影响。
2. Log4j版本详细信息
从 Log4j 2.15.0 开始,默认情况下禁用消息查找功能。配置中的查找仍然有效。虽然 Log4j 2.15.0 有一个选项可以以这种方式启用查找,但强烈建议用户不要启用它。为 JNDI 连接引入了白名单机制,缺省情况下只允许本地主机。发现 2.15.0 版本存在其他漏洞,因此不建议使用。
从版本 2.16.0(对于 Java 8)开始,消息查找功能已完全删除。配置中的查找仍然有效。此外,Log4j 现在缺省情况下会禁用对 JNDI 的访问。现在需要显式启用配置中的 JNDI 查找。建议用户不要在 Log4j 2.16.0 中启用 JNDI,因为它仍然允许 LDAP 连接。如果需要 JMS 追加器,请使用以下版本之一:2.3.1、2.12.2、2.12.3 或 2.17.0:从这些版本开始,JNDI 连接中仅支持 JAVA 协议。
从版本 2.12.2(对于 Java 7)和 2.3.1(对于 Java 6),消息查找功能已被完全删除。配置中的查找仍然有效。此外,Log4j 现在缺省情况下会禁用对 JNDI 的访问。现在需要显式启用配置中的 JNDI 查找。启用后,JNDI 将仅支持 JAVA 协议,对 LDAP 协议的支持已被删除。
从版本 2.17.0(对于 Java 8)开始,对 LDAP 协议的支持已被删除,并且 JNDI 连接中仅支持 JAVA 协议。
从版本 2.17.0(对于 Java 8)、2.12.3(对于 Java 7)和 2.3.1(对于 Java 6),启用 JNDI 的属性已从 'log4j2.enableJndi' 重命名为三个单独的属性:"log4j2.enableJndiLookup"、"log4j2.enableJndiJms"和 "log4j2.enableJndiContextSelector"。
3. Log4j官网发布的缓解措施
1、 Log4j 1.x缓解措施
Log4j 1.x没有查找,因此风险较低。使用 Log4j 1.x 的应用程序仅在其配置中使用 JNDI 时才容易受到此攻击。已针对此漏洞提交了一个单独的 CVE (CVE-2021-4104)。缓解措施:审核日志记录配置,以确保它没有配置 JMSAppender。没有 JMSAppender 的 Log4j 1.x 配置不受此漏洞的影响。
2、 Log4j 2.x缓解措施
实现以下缓解技术之一:
- 升级到 Log4j 2.3.1(适用于 Java 6)、2.12.3(适用于 Java 7)或 2.17.0(适用于 Java 8 及更高版本)。
- 否则,在 2.16.0 以外的任何发行版中,您可以从类路径中删除 JndiLookup 类:zip -q -d log4j-core-*.jar org/apache/logging/log4j/core/lookup/JndiLookup.class。
请注意,只有 log4j-core JAR 文件受此漏洞影响。仅使用 log4j-api JAR 文件而不使用 log4j-core JAR 文件的应用程序不受此漏洞的影响。
另请注意,Apache Log4j 是唯一受此漏洞影响的日志记录服务子项目。其他项目,如Log4net和Log4cxx不受此影响。
3、 不可信的缓解措施
在2.15.0版本中,当配置有包含上下文查找的模块(例如,$${ctx:loginId})时仍然容易受到攻击。当攻击者可以控制线程上下文时,他们可能会注入JNDI Lookup模块,该模块将导致 JNDI 连接。虽然 Log4j 2.15.0 尽最大努力尝试将 JNDI 连接限制在本地,但仍有一些方法可以绕过此操作,用户不应依赖此连接。
为此提出了新的 CVE(CVE-2021-45046)。
缓解措施包括:对于 >= 2.10 的版本,将系统属性 log4j2.formatMsgNoLookups 或环境变量 LOG4J_FORMAT_MSG_NO_LOOKUPS 设置为 true;对于 >= 2.7 和 <= 2.14.1 的版本,将修改日志记录配置以禁用使用 %m{nolookups}、%msg{nolookups} 或 %message{nolookups} 进行消息查找。
这些措施不足的原因是,除了上面提到的线程上下文攻击媒介之外,Log4j中仍然存在可能发生消息查找的代码路径:已知示例是使用Logger.printf("%s",userInput)的应用程序,或者使用自定义消息工厂的应用程序,其中生成的消息不实现StringBuilderFormattable。可能还有其他攻击媒介。
最安全的做法是将 Log4j 升级到安全版本,或者从 log4j-core jar 中删除 JndiLookup 类。
4. Spring官网发布的log4j2的漏洞缓解措施
Log4J2漏洞可以允许攻击者远程执行代码。该漏洞已在Log4J -core jar中使用CVE-2021-44228报告,并已在Log4J v2.15.0中修复。
Spring Boot用户只有在将默认日志系统切换到Log4J2时才会受到此漏洞的影响。在spring-boot-starter-logging中包含的log4j-to-slf4j和log4j-api jar不能单独使用。只有使用log4j-core并在日志消息中包含用户输入的应用程序才容易受到攻击。
即将发布的v2.5.8和v2.6.2版本(2021年12月23日发布)将采用Log4J v2.17.0,但由于这是一个如此严重的漏洞,如果需要覆盖Spring的依赖管理,并尽快升级Log4J2依赖。Spring提供了以下缓解措施。
4、 Gradle
对于Gradle用户,可以按照下面的说明更新version属性,导入BOM或者使用aresolutionStrategy。
- 对于大多数用户,设置log4j2。版本属性就足够了:
ext['log4j2.version'] = '2.17.0' |
- 如果使用的是Gradle的平台支持,而不是spring的依赖管理插件,那么可以在Log4J BOM中添加一个依赖:
implementation(platform("org.apache.logging.log4j:log4j-bom:2.17.0")) |
- 如果无法使用这两个方法中的任何一个,那么可以声明一个resoltionstrategy:
configurations.all { resolutionStrategy.eachDependency { DependencyResolveDetails details -> if (details.requested.group == 'org.apache.logging.log4j') { details.useVersion '2.17.0' } } } |
无论选择哪种方法,若要检查是否已应用替代,都可以运行以下命令查看版本:
./gradlew dependencyInsight --dependency log4j-core
5、 Maven
对于Maven用户,您可以按照这些说明并设置log4j2。版本属性。
- 如果正在使用父POM,可以设置log4j2。版本属性:
<properties> <log4j2.version>2.17.0</log4j2.version> </properties> |
- 如果没有使用父POM,而是导入spring-boot-dependencies,你需要使用一个<dependencyManagement>:
<dependencyManagement> <dependencies> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-bom</artifactId> <version>2.17.0</version> <scope>import</scope> <type>pom</type> </dependency> ... other dependencies including spring-boot-dependencies </dependencies> </dependencyManagement> |
要检查是否应用了覆盖,运行 ./mvnw dependency:list | grep log4j,并检查版本为2.17.0。
5. 复现Log4j的bug
1、复现攻击方服务
2、复现被攻击方服务
3、部署服务,复现攻击
4、攻击结果
6. 缓解Log4j的bug
1、使用启动服务时增加log4j2.formatMsgNoLookups配置缓解
再次复现攻击
正常输出,未发生远程请求调用 |
2、使用Spring官网提供的gradle的第三种方式缓解
修改log4j依赖关系
部署服务,再次复现攻击
正常输出,未发生远程请求调用
|
7. 数据来源
1、Log4j官网:
Log4j – Apache Log4j Security Vulnerabilities
2、Sping 官网:
Log4J2 Vulnerability and Spring Boot