EL and Cross Site Scripting attacks - JSP 2 functions to the rescue 2

Posted by Michael Studman Tue, 01 Jun 2004 03:00:00 GMT

The JSP expression language (EL) has made writing JSPs so much more pleasurable but like standard JSP expressions you need to take care they don't expose your site to Cross Site Scripting (XSS) attacks. JSP 2.0, however, gives us a way to ensure our JSPs are both XSS-safe and compact.

Matt, over at Madbean, points out that whenever you have an EL outside a <c:out value="${someExpression}"> JSTL action tag you may be in danger of opening up yourself to a XSS attack. Naturally the solution is to ensure all output that could possibly have injected code (parameters etc), is wrapped in this tag when being output. In practice this can be cumbersome.

Where you might ordinarily have:

   <fmt:message key="someResourceKey">
       <fmt:param value="${param.someRequestParameter}"/>
   </fmt:message>

You should actually have:

   <fmt:message key="someResourceKey">
       <fmt:param>
           <c:out value="${param.someRequestParameter}" escapeXml="true"/>
       </fmt:param>
       <%-- Note, the escapeXml attribute defaults to 
               true but is here for emphasis --%>
   </fmt:message>

Not so painful, I hear you say. But what happens when you have a tag that doesn't allow you to set the value by tag body rather than by attribute?

Well, you have to do something like this:

    <c:set var="myEscapedVar" scope="page">
        <c:out value="${param.someRequestParameter}" escapeXml="true"/>
    </c:set>
    <some:tag value="${pageScope.myEscapedVar}"/>

Have to use that tag a few times in a page on a few different values? It can get quite nasty.

JSP 2 functions to the rescue

To recap, JSP 2 functions are simple Java functions that are made available to JSP EL expressions through the same mechanism as custom tags (taglibs). JSTL 1.1 (part of JSP 2.0) comes with some long overdue functions such as length() which lets you find the length of a collection, array and so on.

They're simple to write but I'll leave a detailed explanation of how to others.

What if you were to write a very simple JSP function that escaped the XML and printed the string for you instead of relying on the c:out / c:set solution above?

Your function definition would look something like this:

   public static String escapeXml(String value)
   {
       ...
       ...
       return escapedValue;
   }

And the two examples above would be rewritten like this:

   <% taglib prefix="xss" uri="http://www.whatever.com/jsp/xss">
   ...
   ...
   <fmt:message key="someResourceKey">
       <fmt:param value="${xss:escapeXml(param.someRequestParameter)}"/>
   </fmt:message>
   <% taglib prefix="xss" uri="http://www.whatever.com/jsp/xss">
   ...
   ...
    <some:tag value="${xss:escapeXml(param.someRequestParameter)}"/>

This makes for more concise XSS-safe JSPs, me thinks.

Final words: XSS-safe JSP expressions

DeveloperWorks explored this issue back in 2002 in an interesting article found here. Of course, this predates EL and so only addresses XSS with respect to JSP expressions.
e.g.

<%= request.getParameter("FOO")%>

Their solution was to implement a tag similar in effect (if not intent) to the c:out tag where XML-sensitive characters of the value attribute are escaped.

Their solution presents the same problem I've discussed today - overly verbose JSPs. With a bit of JSP jiggery-pokery a similarly brief solution can be made to work for those still wading in JSP expression goo. I imagine it would involve: a JSP base class declaring a method similar to escapeXml(); JSPs that derive from this base class; and XSS-risky JSP expressions enclosed in escapeXml() calls
e.g.

<%= escapeXml(request.getParameter("FOO"))%>

And another thing

I hope there aren't any XSS holes in my site but if there are, please let me know