3 minute read

对应CVE-2021-44228

漏洞在12月10号暴出来:打印的日志含有jndi lookup 表达式,即被解析

In Apache Log4j2 versions up to and including 2.14.1 (excluding security releases 2.3.1, 2.12.2 and 2.12.3), the JNDI features used in configurations, log messages, and parameters do not protect against attacker-controlled LDAP and other JNDI related endpoints. An attacker who can control log messages or log message parameters can execute arbitrary code loaded from LDAP servers when message lookup substitution is enabled.

12月4号官方库有提交,限制了JNDI只能访问localhost(2.15.0):https://github.com/apache/logging-log4j2/commit/c77b3cb39312b83b053d23a2158b99ac7de44dd3

此时的修复方案有设环境变量log4j2.formatMsgNoLookups/LOG4J_FORMAT_MSG_NO_LOOKUPS(仍然存在其他利用路径)、删除log4j-core jar中的JndiLookup.class(只防止了RCE,但消息中仍然可以注入lookup string,因为2.15还没禁用message lookup,导致类似CVE-2021-45105的context lookup 一样的stackoverflow(uncontrolled recursion from self-referential lookups),或在日志中泄漏敏感信息)。唯一真正的修复方案还是更新到新版本

This page previously mentioned other mitigation measures, but we discovered that these measures only limit exposure while leaving some attack vectors open.

The 2.15.0 release was found to still be vulnerable when the configuration has a Pattern Layout containing a Context Lookup (for example, $${ctx:loginId}). When an attacker can control Thread Context values, they may inject a JNDI Lookup pattern, which will be evaluated and result in a JNDI connection. While Log4j 2.15.0 makes a best-effort attempt to restrict JNDI connections to localhost by default, there are ways to bypass this and users should not rely on this.

A new CVE (CVE-2021-45046, see above) was raised for this.

Other insufficient mitigation measures are: setting system property log4j2.formatMsgNoLookups or environment variable LOG4J_FORMAT_MSG_NO_LOOKUPS to true for releases >= 2.10, or modifying the logging configuration to disable message lookups with %m{nolookups}, %msg{nolookups} or %message{nolookups} for releases >= 2.7 and <= 2.14.1.

The reason these measures are insufficient is that, in addition to the Thread Context attack vector mentioned above, there are still code paths in Log4j where message lookups could occur: known examples are applications that use Logger.printf(“%s”, userInput), or applications that use a custom message factory, where the resulting messages do not implement StringBuilderFormattable. There may be other attack vectors.

The safest thing to do is to upgrade Log4j to a safe version, or remove the JndiLookup class from the log4j-core jar.

之后又发现其他利用方式,cve-2021-45046: 日志pattern中含有context lookup, 攻击者可以在MDC中写jndi lookp

When the logging configuration uses a non-default Pattern Layout with a Context Lookup (for example, $${ctx:loginId}),attackers with control over Thread Context Map (MDC) input data can craft malicious input data using a JNDI Lookup pattern, resulting in an information leak and remote code execution in some environments and local code execution in all environments

12月12号默认关闭了JNDI: https://github.com/apache/logging-log4j2/commit/c362aff473e9812798ff8f25f30a2619996605d5

12月13号将日志消息的 lookup功能彻底删除(配置中的lookup仍保留),并且jndi不再支持ldap协议只支持java协议:https://github.com/apache/logging-log4j2/commit/27972043b76c9645476f561c5adc483dec6d3f5d

后续对其他地方的JNDI使用也做了限制

  • https://github.com/apache/logging-log4j2/commit/ab2fb451d248702880a231646dace6b3ec9d98c2
  • https://github.com/apache/logging-log4j2/commit/be97ee03cd5081b66b28c029fb3b10d3ce57b1f8
  • https://github.com/apache/logging-log4j2/commit/80eaa5cdaef536c2163aa3a230ddaee24e03a4ff
  • https://github.com/apache/logging-log4j2/commit/8e18c130c7094b12138d7fab6b91bd8701ff00ee

完整发布历史

As of Log4j 2.15.0 the message lookups feature was disabled by default. Lookups in configuration still work. While Log4j 2.15.0 has an option to enable Lookups in this fashion, users are strongly discouraged from enabling it. A whitelisting mechanism was introduced for JNDI connections, allowing only localhost by default. The 2.15.0 release was found to have additional vulnerabilities and is not recommended.

From version 2.16.0 (for Java 8), the message lookups feature has been completely removed. Lookups in configuration still work. Furthermore, Log4j now disables access to JNDI by default. JNDI lookups in configuration now need to be enabled explicitly. Users are advised not to enable JNDI in Log4j 2.16.0, since it still allows LDAP connections. If the JMS Appender is required, use one of these versions: 2.3.1, 2.12.2, 2.12.3 or 2.17.0: from these versions onwards, only the JAVA protocol is supported in JNDI connections.

From version 2.12.2 (for Java 7) and 2.3.1 (for Java 6), the message lookups feature has been completely removed. Lookups in configuration still work. Furthermore, Log4j now disables access to JNDI by default. JNDI lookups in configuration now need to be enabled explicitly. When enabled, JNDI will only support the JAVA protocol, support for the LDAP protocol has been removed.

From version 2.17.0 (for Java 8), support for the LDAP protocol has been removed and only the JAVA protocol is supported in JNDI connections.

From version 2.17.0 (for Java 8), 2.12.3 (for Java 7) and 2.3.1 (for Java 6), the property to enable JNDI has been renamed from ‘log4j2.enableJndi’ to three separate properties: ‘log4j2.enableJndiLookup’, ‘log4j2.enableJndiJms’, and ‘log4j2.enableJndiContextSelector’.

log4j安全官网

java JNDI 的解释

由于JNDI注入动态加载的原理是使用Reference引用Object Factory类,其内部在上文中也分析到了使用的是URLClassLoader,所以不受java.rmi.server.useCodebaseOnly=false属性的限制。 但是不可避免的受到 com.sun.jndi.rmi.object.trustURLCodebase、com.sun.jndi.cosnaming.object.trustURLCodebase的限制。

所以,JNDI-RMI注入方式有: * codebase(JDK 6u132、7u122、8u113之前可以) * 利用本地Class Factory作为Reference Factory

JNDI-LDAP注入方式: * codebase(JDK 11.0.1、8u191、7u201、6u211之前可以) * serialize(两个切入点)