package org.gcube.isdashboard.config; import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.core.pattern.CompositeConverter; import java.util.Collections; import java.util.HashMap; import java.util.Map; import org.slf4j.Marker; import org.slf4j.MarkerFactory; import org.springframework.boot.ansi.AnsiColor; import org.springframework.boot.ansi.AnsiElement; import org.springframework.boot.ansi.AnsiOutput; import org.springframework.boot.ansi.AnsiStyle; /** * Log filter to prevent attackers from forging log entries by submitting input containing CRLF characters. * CRLF characters are replaced with a red colored _ character. * * @see Log Forging Description * @see JHipster issue */ public class CRLFLogConverter extends CompositeConverter { public static final Marker CRLF_SAFE_MARKER = MarkerFactory.getMarker("CRLF_SAFE"); private static final String[] SAFE_LOGGERS = { "org.hibernate", "org.springframework.boot.autoconfigure", "org.springframework.boot.diagnostics", }; private static final Map ELEMENTS; static { Map ansiElements = new HashMap<>(); ansiElements.put("faint", AnsiStyle.FAINT); ansiElements.put("red", AnsiColor.RED); ansiElements.put("green", AnsiColor.GREEN); ansiElements.put("yellow", AnsiColor.YELLOW); ansiElements.put("blue", AnsiColor.BLUE); ansiElements.put("magenta", AnsiColor.MAGENTA); ansiElements.put("cyan", AnsiColor.CYAN); ELEMENTS = Collections.unmodifiableMap(ansiElements); } @Override protected String transform(ILoggingEvent event, String in) { AnsiElement element = ELEMENTS.get(getFirstOption()); if ((event.getMarker() != null && event.getMarker().contains(CRLF_SAFE_MARKER)) || isLoggerSafe(event)) { return in; } String replacement = element == null ? "_" : toAnsiString("_", element); return in.replaceAll("[\n\r\t]", replacement); } protected boolean isLoggerSafe(ILoggingEvent event) { for (String safeLogger : SAFE_LOGGERS) { if (event.getLoggerName().startsWith(safeLogger)) { return true; } } return false; } protected String toAnsiString(String in, AnsiElement element) { return AnsiOutput.toString(element, in); } }