9

I'm working on preventing cross site scripting (XSS) in a Java, Spring based, Web application. I have already implemented a servlet filter similar to this example http://greatwebguy.com/programming/java/simple-cross-site-scripting-xss-servlet-filter/ which sanitizes all the input into the application. As an extra security measure I would like to also sanitize all output of the application in all JSPs. I have done some research to see how this could be done and found two complementary options.

One of them is the use of Spring's defaultHtmlEscape attribute. This was very easy to implement (a few lines in web.xml), and it works great when your output is going through one of spring's tags (ie: message, or form tags). The other option I have found is to not directly use EL expressions such as ${...} and instead use <c:out value="${...}" />

That second approach works perfectly, however due to the size of the application I am working on (200+ JSP files). It is a very cumbersome task to have to replace all inappropriate uses of EL expressions with the c:out tag. Also it would become a cumbersome task in the future to make sure all developers stick to this convention of using the c:out tag (not to mention, how much more unreadable the code would be).

Is there alternative way to escape the output of EL expressions that would require fewer code modifications?

ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
driangle
  • 11,601
  • 5
  • 47
  • 54

3 Answers3

11

Since Servlet 2.5/JSP 2.1 you could create a custom ELResolver which does that. You can register it in ServletContextListener#contextInitialized().

@Override
public void contextInitialized(ServletContextEvent event) {
    JspFactory.getDefaultFactory()
        .getJspApplicationContext(event.getServletContext())
        .addELResolver(new YourCustomELResolver());
}

In the ELResolver#getValue() you could do the escaping job.

Your only problem is that you will be unable to display HTML there where it's allowed (i.e. already sanitized from malicious tags/attributes by kind of a whitelist so that you end up with innocent tags like Jsoup can do).


That said, I disagree the necessity to escape XSS during input by the Filter as you mentioned in 1st paragraph of the question. You risk double-escaping. You only need to escape it at exactly that point where it can possibly harm, i.e. straight in the view side there where it's going to be inlined among HTML, the output. I recommend to get rid of that so-called XSS filter and concentrate you on fixing it in the view side by either using JSTL <c:out> or fn:escapeXml() (or a custom EL resolver, but that's definitely not the normal approach). The future code maintainers will be greatly thankful.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • 1
    Don't use `fn:escapeXml` to escape HTML. It will generate `'`, which is not a standard HTML entity. – Roland Illig Dec 17 '10 at 16:05
  • 1
    @Roland: no, it doesn't. It generates `'` which is valid in both HTML and XML (as does `c:out`). – BalusC Dec 17 '10 at 16:12
  • Ah, that's great. So I must have confused with some other `escapeXml` function. To be sure, I looked it up in the JSTL specification, where this is explicitly mentioned. – Roland Illig Dec 17 '10 at 18:45
  • hmm, I tried doing this but the call to JspFactory.getDefaultFactory returns null, Do you know I may be missing? I'm running on Tomcat 6.0.20 and using the jsp-api 2.1 jar. – driangle Dec 17 '10 at 22:27
  • To be clear, you don't have any servletcontainer-specific JAR's in your `WEB-INF/lib` folder, right? Your `web.xml` is also declared as per Servlet 2.5? – BalusC Dec 17 '10 at 22:48
  • the version in web.xml is 2.5. However I am including other servletcontainer-specific Jars (through maven). The following are in my pom.xml: jstl-1.2.jar , servlet-api-2.5.jar. It's strange, when I don't include the jsp-api-2.1.jar I can see the compiled jsp classes are using JspFactory, but I cannot include that class in my ServletContextListener (not found on my classpath). When I do include that jar, I can include it in my listener, but the compiled jsps throw a NPE because getDefaultFactory returns null. – driangle Dec 17 '10 at 23:28
1

This blog post describes a custom ELResolver which escapes EL expression values of type String. Registering this custom ELResolver will cause it to escape the output of all EL expressions. In the exceptional cases where a JSP must programmatically output HTML, you require a mechanism that does not involve an EL expression, such as a custom tag or a scriptlet:

<%= "Java expression hopefully returning safe HTML" %>
Chin Huang
  • 12,912
  • 4
  • 46
  • 47
1

I agree you shouldn't have to use c:out around every variable. I wrote a blog describing why at http://tech.finn.no/2011/04/08/xss-protection-whos-responsibility/

It touches on much that is said here.

mck
  • 11
  • 1