springboot logback 日志注入安全问题 统一处理

springboot logback 日志注入安全问题 统一处理

码农世界 2024-05-15 前端 58 次浏览 0个评论

背景

日志注入一般指的是恶意用户输出换行等内容,混淆正常的日志,导致排查问题是无法正确定位问题,因此,我们需要对要打印的日志内容进行过滤。

但是,如果是每个接口单独处理的话,成本较高,因此,我们需要一个统一处理的机制。

当然,统一处理可能会误伤正常的日志,这个需要自己进行斟酌了。我们在绝大情况下不会在打印日志的内容中使用换行等特殊字符,所以这样处理我认为是比较稳妥的。

这个处理仅会对用户输入的参数进行处理,不会对堆栈的正常的内容处理,所以大部分的日志是可以正常打印出来的。

方案

springboot集成的logback,其配置文件是 org/springframework/boot/logging/logback/base.xml,其默认参数配置都在org/springframework/boot/logging/logback/defaults.xml。我们不打算修改这些配置,而是沿用。

我们对logback进行定制,spring集成的默认log_pattern为:-%clr(%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd'T'HH:mm:ss.SSSXXX}}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr(%applicationName[%15.15t]){faint} %clr(${LOG_CORRELATION_PATTERN:-}){faint}%clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}},中间可以全部不管,输出的重点就是靠后部分的%m,这个是一个Converter,对消息进行处理,默认是不进行任何处理,直接输出原消息,我们对他进行定制。

我们自定义自己的Converter:

import ch.qos.logback.classic.pattern.ClassicConverter;
import ch.qos.logback.classic.spi.ILoggingEvent;
import org.slf4j.helpers.MessageFormatter;
/**
 * @author 
 */
public class LineSeparatorConverter extends ClassicConverter {
    @Override
    public String convert(ILoggingEvent event) {
        Object[] argumentArray = event.getArgumentArray();
        // 没有用户传入的参数,直接返回
        if (argumentArray == null || argumentArray.length == 0) {
            return event.getFormattedMessage();
        }
        Object[] argumentArrayProcessed = new Object[argumentArray.length];
        for (int i = 0; i < argumentArray.length; i++) {
            Object o = argumentArray[i];
            if (o == null || o instanceof Throwable) {
                argumentArrayProcessed[i] = o;
            } else {
                String oString = o.toString();
                argumentArrayProcessed[i] = cleanLineSeparator(oString);
            }
        }
        return getFormattedMessage(event.getMessage(), argumentArrayProcessed);
    }
    public String getFormattedMessage(String message, Object[] argumentArray) {
        String formattedMessage;
        if (argumentArray != null) {
            formattedMessage = MessageFormatter.arrayFormat(message, argumentArray).getMessage();
        } else {
            formattedMessage = message;
        }
        return formattedMessage;
    }
    private String cleanLineSeparator(String line) {
        if (line == null || line.isEmpty()) {
            return line;
        }
        return line.replace("\n", "\\n").replace("\r", "\\r");
    }
}

然后,声明logback-spring.xml,使用spring的默认配置,并且覆盖%m的默认Converter,改成我们自己的



    
    
    

如果放到了resources目录下,该文件应该可以正常识别到,不需要额外配置。

如果日志处理是一个maven的子模块,那就手动声明一下文件位置

logging.config=classpath:logback-spring.xml,

如果放到其他目录,写成:logging.config=file:/xxx/xxx/logback-spring.xml

转载请注明来自码农世界,本文标题:《springboot logback 日志注入安全问题 统一处理》

百度分享代码,如果开启HTTPS请参考李洋个人博客
每一天,每一秒,你所做的决定都会改变你的人生!

发表评论

快捷回复:

评论列表 (暂无评论,58人围观)参与讨论

还没有评论,来说两句吧...

Top