Matt RaibleMatt Raible is a Web Architecture Consultant specializing in open source frameworks.

10+ YEARS


Over 10 years ago, I wrote my first blog post. Since then, I've authored books, had kids, traveled the world, found Trish and blogged about it all.

Fixing XSS in JSP 2

Way back in 2007, I wrote about Java Web Frameworks and XSS. My main point was that JSP EL doesn't bother to handle XSS.

Of course, the whole problem with JSP EL could be solved if Tomcat (and other containers) would allow a flag to turn on XML escaping by default. IMO, it's badly needed to make JSP-based webapps safe from XSS.

A couple months later, I proposed a Tomcat enhancement to escape JSP's EL by default. I also entered an enhancement request for this feature and attached a patch. That issue has remained open and unfixed for 3 and 1/2 years.

Yesterday, Chin Huang posted a handy-dandy ELResolver that XML-escapes EL values.

I tried Chin's resolver in AppFuse today and it works as well as advertised. To do this, I copied his EscapeXML*.java files into my project, changed the JSP API's Maven coordinates from javax.servlet:jsp-api:2.0 to javax.servlet.jsp:jsp-api:2.1 and added the listener to web.xml.

With Struts 2 and Spring MVC, I was previously able to have ${param.xss} and pass in ?xss=<script>alert('gotcha')</script> and it would show a JavaScript alert. After using Chin's ELResolver, it prints the string on the page instead of displaying an alert.

Thanks to Chin Huang for this patch! If you're using JSP, I highly recommend you add this to your projects as well.

Posted in Java at Feb 28 2011, 02:08:46 PM MST 7 Comments
Comments:

Security is a complicated issue. Can you please highlight an example of why allow someone to execute javascript through JSTL ${param} request parameters is a security hole? How does this allow someone to execute Javascript on another site, hence XSS vulnerability?

Posted by Jay Spring on March 01, 2011 at 02:18 PM MST #

Registering this custom ELResolver will cause it to escape the output of all EL expressions. If you want a JSP to programmatically output HTML, you have to use a mechanism that does not involve an EL expression, such as a custom tag or old-school JSP scriptlet.

Posted by Chin Huang on March 01, 2011 at 02:36 PM MST #

This is a really clever use of an ELResolver to solve the JSP unescaped content problem. Nice work.

The big problem I see with this approach is that there is no way to disable the XML escaping of content. On every project I've worked on there are always a few use cases where some of the content being rendered in a JSP is HTML content, requiring unescaped strings to be rendered. If *all* EL resolving is escaped then it becomes impossible to ever render any unescaped content. I don't think resorting an a JSP scriptlet is a good solution, as normally my projects will have scripting-invalid=true. Even if you implemented a custom tag specifically to render HTML content such as this, you wouldn't be able to use any EL to pass the property into the tag from a JSP!

The c:out tag is also broken by this approach, whereby the default behaviour of escapeXml=true now double-escapes any HTML content, and escapeXml=false is ignored (as the EL has already been resolved, and escaped, prior to the value being passed in to the tag), effectively now behaving as escapeXml=true.

Do you have any clever ideas or suggestions of how to circumvent this problem? A few options I've come up with, none of which I'm too enamoured with, are...

- Allow a page-scoped property 'el.escapeXml=false' to be set. Check for this in the ELResolver and if set and false, don't do the escaping.

- Allow all EL expressions to be suffixed with 'noEscapeXml' i.e. ${someProperty.noEscapeXml} - Have the ELResolver wrap the String that is currently being escaped in a custom object 'EscapableStringWrapper' whose toString() method performs the escaping. The resolver could then check for such an object being passed in as the 'base' object in a getValue() call.

These approaches all seem quite hacky to me - perhaps you can think of some clever alternative?

Posted by James Wiltshire on March 03, 2011 at 10:52 PM MST #

I implemented a custom tag to surround JSP code in which EL expressions should not be escaped:
<wae:out escapeXml="false">
  I hope this expression returns safe HTML: ${user.name}
</wae:out>
Under the hood, it sets a pageScope attribute to control the custom ELResolver's escaping function, but application developers should not access this attribute anyway.

Posted by Chin Huang on March 07, 2011 at 09:59 PM MST #

Someone could expalin to me why in this resolver is needed the flag excludeMe. Would it work without it? Thx.

Posted by casopi on April 26, 2012 at 09:56 AM MDT #

You could change the JSP compiler to write escaped value when using ${} to output on a jsp page and thus not breaking EL functions nor JSTL.
e.g. Using this option, <c:out will still work fine

DrawBacks :
- This a vendor specific solution and can not be done without modifying compiler code

Posted by Benoit Prat on May 30, 2012 at 10:19 AM MDT #

Unfortunately, HTML escaping isn't enough so this approach is fundamentally broken. All you're getting is a false sense of security, because EL can be used in many places where HTML escaping simply doesn't work to prevent XSS. See:

http://www.coverity.com/srl/a-guide-to-fixing-xss-for-devs.html

Posted by Andy on April 04, 2013 at 11:06 AM MDT #

Post a Comment:
  • HTML Syntax: Allowed