3
  1. Is it enough to upgrade log4j-core and log4j-api to 2.15.0 but leave log4j-slf4j-impl, which is a binding library, to 2.14.1, given that mvn dependency:tree suggests that log4j-slf4j-impl:2.14.1 is depending on log4j-core:2.15.0 and log4j-api:2.15.0 and the logging works appropriately? I am asking this because at the moment of havoc yesterday, log4j-slf4j-impl still haven't had 2.15.0 released.

  2. Has the fix in 2.15.0 included a change to LOG4J_FORMAT_MSG_NO_LOOKUPS being set to true? Running the following unit test suggests that the variable is still false with all of the dependencies in the 1st question being set to version 2.15.0:

import org.apache.logging.log4j.util.PropertiesUtil;

@Test
public void testLog4j() {
    PropertiesUtil props = PropertiesUtil.getProperties();
    boolean val = props.getBooleanProperty("LOG4J_FORMAT_MSG_NO_LOOKUPS");
    System.out.println(val);
}
Philipp
  • 48,867
  • 8
  • 127
  • 157
53c
  • 133
  • 4

1 Answers1

3

The fix was: Log4j2 no longer formats lookups in messages by default

log4j-slf4j-impl doesn't include the vulnerable code so should be fine but is now updated to 2.15.0.

The LOG4J_FORMAT_MSG_NO_LOOKUPS doesn't exist in your test so it's returning false but that's not how it's being read within log4j. The property is now being read as PropertiesUtil.getProperties().getBooleanProperty("log4j2.formatMsgNoLookups", true) so if it doesn't exist, then it'll default to true. This can be checked via:

import org.apache.logging.log4j.core.util.Constants;
...
System.out.println(Constants.FORMAT_MESSAGES_PATTERN_DISABLE_LOOKUPS);

In the new version, this is true but also not used. Instead lookups have to be enabled via a pattern containing %msg{lookups}

The test from MessagePatternConverterTest should show whether the lookups are happening:

@Test
public void testDisabledLookup() {
    final Configuration config = new DefaultConfigurationBuilder()
            .addProperty("foo", "bar")
            .build(true);
    final MessagePatternConverter converter = MessagePatternConverter.newInstance(
            config, new String[] {"nolookups"});
    final Message msg = new ParameterizedMessage("${foo}");
    final LogEvent event = Log4jLogEvent.newBuilder() //
            .setLoggerName("MyLogger") //
            .setLevel(Level.DEBUG) //
            .setMessage(msg).build();
    final StringBuilder sb = new StringBuilder();
    converter.format(event, sb);
    assertEquals("${foo}", sb.toString(), "Expected the raw pattern string without lookup");
}
fgb
  • 146
  • 2