Bruce Brouwer created LOG4J2-439:
------------------------------------
Summary: Create a LogEventPatternConverter to escape newlines and
HTML special characters
Key: LOG4J2-439
URL: https://issues.apache.org/jira/browse/LOG4J2-439
Project: Log4j 2
Issue Type: New Feature
Components: Layouts
Affects Versions: 2.0-beta9
Reporter: Bruce Brouwer
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|http://owasp-esapi-java.googlecode.com/svn/trunk_doc/2.0-rc7/apidocs/org/owasp/esapi/Logger.html],
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:
{code:xml}
<PatternLayout pattern="%d %-5p [%t] %c %encode{%m}%n"/>
{code}
And logging this message:
{code}
LOG.warn("hi\n & <h1> there");
{code}
Would result in this being logged:
{code}
2013-10-28 16:31:21,606 WARN [main] example.Test hi\n & <h1> there
{code}
instead of this (which shows the potential for log forging):
{code}
2013-10-28 16:31:21,606 WARN [main] example.Test hi
& <h1> there
{code}
This is roughly the code I used:
{code}
@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(">", ">"));
}
}
{code}
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?
--
This message was sent by Atlassian JIRA
(v6.1#6144)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]