Description
To prevent log forging and HTML based attacks from viewing logs in a browser, we could add a LogEventPatternConverter that escapes newlines and HTML special characters. ESAPI has a method to do this, but it doesn't have any of the nice API features that Log4j 2 has.
I was able to create a LogEventPatternConverter to do this. Note, this is only a proof of concept. I didn't try to exhaustively list all the special characters that might need to be replaced. I also didn't provide any configuration so we could choose to not escape HTML, for example.
With this configuration:
<PatternLayout pattern="%d %-5p [%t] %c %encode{%m}%n"/>
And logging this message:
LOG.warn("hi\n & <h1> there");
Would result in this being logged:
2013-10-28 16:31:21,606 WARN [main] example.Test hi\n & <h1> there
instead of this (which shows the potential for log forging):
2013-10-28 16:31:21,606 WARN [main] example.Test hi & <h1> there
This is roughly the code I used:
@Plugin(name = "escape", category = "Converter") @ConverterKeys({ "escape" }) public final class EscapingReplacementConverter extends LogEventPatternConverter { private final List<PatternFormatter> formatters; private EscapingReplacementConverter(final List<PatternFormatter> formatters) { super("escape", "escape"); this.formatters = formatters; } public static EscapingReplacementConverter newInstance(final Configuration config, final String[] options) { if (options.length != 1) { LOGGER.error("Incorrect number of options on escape. Expected 1, received " + options.length); return null; } if (options[0] == null) { LOGGER.error("No pattern supplied on escape"); return null; } final PatternParser parser = PatternLayout.createPatternParser(config); final List<PatternFormatter> formatters = parser.parse(options[0]); return new EscapingReplacementConverter(formatters); } @Override public void format(final LogEvent event, final StringBuilder toAppendTo) { final StringBuilder buf = new StringBuilder(); for (final PatternFormatter formatter : formatters) { formatter.format(event, buf); } toAppendTo.append(buf.toString() .replaceAll("\\r", "\\\\r") .replaceAll("\\n", "\\\\n") .replaceAll("&", "&") .replaceAll("<", "<") .replaceAll(">", ">")); } }
If this sounds good, I would like to hear feedback and ideas on how to make this better. I will then contribute this to the project. Do you think this could this get in 2.0?
Attachments
Attachments
Issue Links
- is duplicated by
-
LOG4J2-1203 Allow filtering of line breaks in layout pattern
- Closed