Introduction #

This page describes the mechanisms in Liferay to escape characters.

All the escape methods are designed to prevent XSS attacks and follows OWASP's recommendations for escaping. They can be found in the class HtmlUtil:

The Functions #

(Methods follow order from OWASP's XSS_Prevention_Rules_Summary).

Data Type Context Code Sample Defense
String HTML Body <span>UNTRUSTED DATA</span> HtmlUtil.escape()
String Safe HTML Attributes <input type="text" name="fname" value="UNTRUSTED DATA"> HtmlUtil.escapeAttribute()
String GET Parameter <a href="/site/search?value=UNTRUSTED DATA">clickme</a> HtmlUtil.escapeURL()
String Untrusted URL in a SRC or HREF attribute <a href="UNTRUSTED URL">clickme</a><iframe src="UNTRUSTED URL" /> HtmlUtil.escapeHREF()
String Untrusted JavaScript link in a SRC or HREF attribute <a href="javascript:someFunction('UNTRUSTED DATA')">clickme</a><iframe src="javascript:someFunction('UNTRUSTED DATA')" /> HtmlUtil.escapeJS()
String CSS Value <div style="width: UNTRUSTED DATA;">Selection</div> HtmlUtil.escapeCSS()
String JavaScript Variable <script>var currentValue='UNTRUSTED DATA';</script><script>someFunction('UNTRUSTED DATA');</script> HtmlUtil.escapeJS()

When to Escape #

Escaping at the right time is important to make sure that 1) data is not escaped multiple times and 2) data is not changed to a different value before all business logic is done processing.

General Rule 1 : Don't escape before persisting #

There's a few reason why it's generally a bad idea to escape the data before it's persisted.

  1. It increases the size of the data that must be stored
  2. You may need the original at some point in the future. If the data is escaped already, it'll be very difficult to get back the original.

General Rule 2 : Escape at the last minute #

Escaping should be done at the last minute. This avoids situations where the data is escaped before all the business logic is done. Practically, this means that most of the escaping should be done in .jsp files and not in .java files.

Pattern 1 : LanguageUtil #

The values in a Language.properties file may contain HTML elements and they are always safe. So, you should avoid

HtmlUtil.escape(LanguageUtil.format(pageContext, "entries-with-tag-x", tagName))

and instead do

LanguageUtil.format(pageContext, "entries-with-tag-x", HtmlUtil.escape(tagName))

Pattern 2 : "javascript:" links #

Placing "javascript:" links into href attribute is causing browsers to double decode the attribute value. This is dangerous when we the value contains URL-encoded characters, because these will be decoded before passing the JS code to the JavaScript runtime environment.

Imagine we want to execute following JavaScript code inside "href" attribute:

javascript:myFunction('http://server/page?param1=param2&backURL=http%3A%2F%2Fserver%2Fpage2')

Avoid this straightforward usage:

<a href="<%= HtmlUtil.escapeAttribute("javascript:myFunction('http://server/page?param1=param2&backURL=http%3A%2F%2Fserver%2Fpage2')") %>">link</a>

Instead use HtmlUtil.escapeJS() to avoid decoding of the URL-encoded characters (%3A and %2F) before they reach JavaScript runtime:

<a href="javascript:myFunction('<%= HtmlUtil.escapeJS("http://server/page?param1=param2&backURL=http%3A%2F%2Fserver%2Fpage2") %>')">link</a>

0 archivos adjuntos
26118 Accesos
Promedio (4 Votos)
La valoración media es de 3.5 estrellas de 5.
Comentarios
Respuestas anidadas Autor Fecha
I don't understand Pattern 1, since the... Marco Glur 11 de febrero de 2011 0:12
Marco, I agree with you about pattern 1 if we... Samuel Kong 26 de diciembre de 2011 1:15

I don't understand Pattern 1, since the Language.properties should be free of formatting (HTML) according to known i18n patterns used in Java (clear separation). Of course there are rare exceptions sometimes.
With escaping in .jsp files, I'd prefer to use scrptlets by exception, which is solved using EL, for instance (${fn:escapeXml('some text with <escaped chars>')})
Publicado el día 11/02/11 0:12.
Marco, I agree with you about pattern 1 if we had clear separation. Unfortunately, we don't have clear separation in the portal's Language.properties files because we want to be able to have text like

Visit <a href="{some-url}">{some-user-name}</a> profile

which mixes text with HTML code. So we need pattern 1 to prevent double escaping.
Publicado el día 26/12/11 1:15 en respuesta a Marco Glur.