1、简介
针对Java的日志系统有多种,本文主要描述如何通过修改配置文件来解决logback和log4j的日志伪造问题。
2、logback
2.1、系统提供的解决方案
在logback.xml
中配置编码器自动转义特殊字符:
复制
<configuration>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %replace(%msg){'[\r\n]', '\\n'}%n</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="CONSOLE" />
</root>
</configuration>
2.2、自定义的解决方案
对于Logback,可以创建自定义转换器:
public class SanitizingConverter extends ClassicConverter {
@Override
public String convert(ILoggingEvent event) {
return event.getFormattedMessage()
.replace("\n", "\\n")
.replace("\r", "\\r");
}
}
再在配置文件中配置自定义的转换器:
<configuration>
<conversionRule conversionWord="sanitizedMsg"
converterClass="com.example.SanitizingConverter"/>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d %sanitizedMsg%n</pattern>
</encoder>
</appender>
</configuration>
2、log4J
2.1 使用过滤器(Filter)
创建自定义Filter:
import org.apache.log4j.spi.Filter;
import org.apache.log4j.spi.LoggingEvent;
public class LogForgeFilter extends Filter {
@Override
public int decide(LoggingEvent event) {
String message = event.getRenderedMessage();
if (message != null && (message.contains("\n") || message.contains("\r"))) {
return Filter.DENY; // 拒绝包含换行符的日志
}
return Filter.NEUTRAL;
}
}
然后在配置中添加:
log4j.appender.CONSOLE.filter.1=com.yourpackage.LogForgeFilter
这种方法由于在异常情况下,会不记录日志,就会导致有些异常的日志被过滤调了,不利于后期的攻击的调查。建议还是使用其它方案,把所有的日志都记录下来。
2.2、Log4J 1.x
2.2.1、系统提供的解决方案
在log4j.properties
中添加或修改以下配置:
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
log4j.appender.CONSOLE.layout.replaceNewlines=true
2.2.2、自定义的解决方案
首先创建一个自定义的Layout类:
import org.apache.log4j.PatternLayout;
import org.apache.log4j.spi.LoggingEvent;
public class SanitizingPatternLayout extends PatternLayout {
@Override
public String format(LoggingEvent event) {
String message = super.format(event);
// 替换换行符和回车符
return message.replace("\n", "\\n").replace("\r", "\\r");
}
}
2. 在log4j.properties
中使用这个自定义Layout:
log4j.appender.CONSOLE.layout=com.example.SanitizingPatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
2.3、Log4J 2
2.3.1、系统提供的解决方案
在log4j2.xml
中使用encode{}
或替换模式:
<Configuration>
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss} [%t] %-5level %logger{36} - %encode{%msg}{CRLF}%n"/>
</Console>
</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>
2.3.2、对所有输出进行编码处理
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} [%t] %-5p %c - %encode{%m}%n
注意:标准Log4j 1.x不直接支持%encode
,需要自定义PatternLayout或使用扩展库