Configuring loggers is security-sensitive. It has led in the past to the following vulnerabilities:
Logs are useful before, during and after a security incident.
Logs are also a target for attackers because they might contain sensitive information. Configuring loggers has an impact on the type of information logged and how they are logged.
This rule flags for review code that initiates loggers configuration. The goal is to guide security code reviews.
You are at risk if you answered yes to any of those questions.
Remember that configuring loggers properly doesn't make them bullet-proof. Here is a list of recommendations explaining on how to use your logs:
This rule supports the following libraries: Log4J, java.util.logging and Logback
// === Log4J 2 ===
import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilderFactory;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.core.*;
import org.apache.logging.log4j.core.config.*;
// Questionable: creating a new custom configuration
abstract class CustomConfigFactory extends ConfigurationFactory {
// ...
}
class A {
void foo(Configuration config, LoggerContext context, java.util.Map<String, Level> levelMap,
Appender appender, java.io.InputStream stream, java.net.URI uri,
java.io.File file, java.net.URL url, String source, ClassLoader loader, Level level, Filter filter)
throws java.io.IOException {
// Creating a new custom configuration
ConfigurationBuilderFactory.newConfigurationBuilder(); // Questionable
// Setting loggers level can result in writing sensitive information in production
Configurator.setAllLevels("com.example", Level.DEBUG); // Questionable
Configurator.setLevel("com.example", Level.DEBUG); // Questionable
Configurator.setLevel(levelMap); // Questionable
Configurator.setRootLevel(Level.DEBUG); // Questionable
config.addAppender(appender); // Questionable: this modifies the configuration
LoggerConfig loggerConfig = config.getRootLogger();
loggerConfig.addAppender(appender, level, filter); // Questionable
loggerConfig.setLevel(level); // Questionable
context.setConfigLocation(uri); // Questionable
// Load the configuration from a stream or file
new ConfigurationSource(stream); // Questionable
new ConfigurationSource(stream, file); // Questionable
new ConfigurationSource(stream, url); // Questionable
ConfigurationSource.fromResource(source, loader); // Questionable
ConfigurationSource.fromUri(uri); // Questionable
}
}
// === java.util.logging ===
import java.util.logging.*;
class M {
void foo(LogManager logManager, Logger logger, java.io.InputStream is, Handler handler)
throws SecurityException, java.io.IOException {
logManager.readConfiguration(is); // Questionable
logger.setLevel(Level.FINEST); // Questionable
logger.addHandler(handler); // Questionable
}
}
// === Logback ===
import ch.qos.logback.classic.util.ContextInitializer;
import ch.qos.logback.core.Appender;
import ch.qos.logback.classic.joran.JoranConfigurator;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.classic.*;
class M {
void foo(Logger logger, Appender<ILoggingEvent> fileAppender) {
System.setProperty(ContextInitializer.CONFIG_FILE_PROPERTY, "config.xml"); // Questionable
JoranConfigurator configurator = new JoranConfigurator(); // Questionable
logger.addAppender(fileAppender); // Questionable
logger.setLevel(Level.DEBUG); // Questionable
}
}
Log4J 1.x is not covered as it has reached end of life.