FreshMarker und OWASP

Anyone involved in security is of course familiar with the Open Web Application Security Project (OWASP). The OWASP is a global non-profit organization dedicated to improving the security of software applications. OWASP provides a variety of resources, tools and best practices to help developers, security researchers and organizations identify and fix potential security vulnerabilities.

The best known is certainly the OWASP Top Ten. The OWASP Top Ten contains important security risks and best practices. Developers can use this list to find out about the most common vulnerabilities, e.g. SQL injection, cross-site scripting (XSS), and implement appropriate preventive measures. In addition to the OWASP Top Ten, various OWASP Java libraries are of particular interest to Java developers.

It will come as no surprise that FreshMarker, like all other template engines, must take precautions against template injection. Template injection is a security vulnerability that occurs when an application handles templates insecurely. Templates are prefabricated files or strings with placeholders that are replaced by data from users or other sources. Similar to FreeMarker, FreshMarker also has an escape mechanism that detects special characters in the interpolations using a harmless variant. The mechanism works well as long as the dynamic values in the interpolation are not text containing html markup. Of course, the mechanism works correctly, but the result is not actually desired.

<h1>This is a header</h1>
<p>This is <i onclick="alert("inject!")">italic</i> and <b>bold</b> text</p>

The text contains the block elements H1 and P and the inline elements I and B. The escape mechanism generates the following output.

&lt;h1&gt;This is a header&lt;/h1&gt;
&lt;p&gt;This is &lt;i onclick=&quot;alert(&quot;inject!&quot;)&quot;&gt;italic&lt;/i&gt; and &lt;b&gt;bold&lt;/b&gt; text&lt;/p&gt;

If it is an online comment, this display would not be particularly attractive because the HTML elements would be displayed in text form. It would be better here not to modify the inline elements. Deactivating the escape mechanism is not a good idea, because otherwise the inserted Javascript code will be delivered.

An escape mechanism is therefore required that produces the following output and removes the Javascript.

This is a header
This is <i>italic</i> and <b>bold</b> text

The block elements have been removed because they usually determine the layout and then change the online display of the comment.

This is where OWASP and its HTML sanitizer library come into play.

<dependency>
    <groupId>com.googlecode.owasp-java-html-sanitizer</groupId>
    <artifactId>owasp-java-html-sanitizer</artifactId>
    <version>20240325.1</version>
</dependency>

This library provides a highly configurable HTML sanitizer. For our use case, we use the ready-made Sanitizers.FORMATTING. This leaves only a few selected inline elements in the text and removes all others.

configuration.registerOutputFormat("OWASP", new OutputFormat() {

  @Override
  public TemplateString escape(Environment environment, String value) {
    return new TemplateString(Sanitizers.FORMATTING.sanitize(value));
  }
});

Template template = configuration.builder().withOutputFormat("HTML").getTemplate("test", """
   <h1>${user}</h1>
   <p><#outputformat 'OWASP'>${content}</#outputformat></p>
   """);

So that this sanitizer can be used via the outputformat directive, we register our custom OutputFormat under the name OWASP. If another variant of the sanitizer is also required, a further OutputFormat can also be registered.

Leave a Comment