Java Web Frameworks and XSS
In preparation for my talk at OSCON next week, I've been doing some research on cross-site scripting and how good Java web frameworks handle it. I'm disappointed to report that the handling of XSS in Java web frameworks is abysmal. First of all, the JSP EL doesn't bother to handle XSS:
With JSP 2.0 you can use the following to emit the description of a "todo" item:
${todo.description}
That's pretty nice. What happens when someone has entered a description like this?
<script type="text/javascript">alert('F#$@ you!');</script>
Well, it executes the JavaScript and pops up a nice little message to you.
...
My question is this: Why in the world did the expert group on the JSP 2.0 JSR decide to make not escaping XML content the default for EL expressions, when they made the opposite decision for c:out
?
(Emphasis mine) If a company/developer wants to make sure their JSP-based code is not susceptible to XSS, they have two choices (as I see it):
- Do lots of code review to make sure <c:out> is used instead of ${}.
- Hack the jsp-compiler/el-engine to escape XML by default.
The good news is #2 doesn't seem to be that hard. I pulled down commons-el yesterday, added a hack to escape XML, re-jarred and put it in Tomcat 5.0.25's classpath. This actually worked and I was impressed it was so easy. However, when I looked at Tomcat 6, commons-el is no longer used and now there's a "jasper-el.jar" in the lib directory. I don't mind modifying another library, but what's the difference between jasper-el and commons-el?
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.
On a related note, there's a couple of web frameworks that I've found to be susceptible to XSS: namely Spring MVC and Struts 2. For Spring MVC, its <form:input> and <form:errors> tags are vulnerable. For Struts 2, OGNL expressions are evaluated, which is way worse than XSS and actually allows you to shutdown the JVM by putting %{@java.lang.System@exit(0)}"
in a text field.
Even though it was surprising for me to see the issues with Struts 2 and Spring MVC, I'm somewhat glad they exist. If I hadn't discovered them, I might blissfully think that Java web frameworks aren't susceptible to XSS. However, it appears they're not only susceptible, but no one is really thinking about XSS when developing these framework. To further prove that theory, the Spring MVC and Struts 2 teams are aware of these issues, have been for quite some time - yet they've done nothing in the form of releasing upgrades or patches.
Seems kinda strange doesn't it?
Posted by Paul Barry on July 19, 2007 at 05:21 PM MDT #
Posted by John on July 19, 2007 at 05:21 PM MDT #
Is your criticism of Struts fair? AFAIK the current issue was only raised 3 days ago here - apparently it needs a release of XWork first (which is done) and a Struts2 release - which is on the agenda.
Also IMO the Struts team has a good history of fixing vulnerabilities - Struts 1.2.8 and Struts 1.2.9 releases were both primarily to fix those types of issues.
re: EL and Tomcat 6 As part of JSR 245 (Servlet 2.5 / JSP 2.1) the expression language was separated out from the Servlet Spec into its own specification document as part of the process to provide a Unified Expression Language for both JSP and JSF. Tomcat 6 now ships with an implementation of the Unified EL (which btw has no Servlet/JSP/JSF dependency) - the el-api.jar in Tomcat is the Spec and the jasper-el jar is the implementation of the Unfied EL.
Posted by Niall on July 19, 2007 at 09:46 PM MDT #
Matt,
Given this feature is in Appfuse, is the implementation completely secure?
Cheers
Charles
Posted by Charles Crouch on July 19, 2007 at 10:35 PM MDT #
Niall - I agree that the Struts team has done a good job of letting the community know that there's a problem and they're working on fixing it. However, there have been no public announcements about this (potentially) huge security hole. All I'm asking for is a blog post from a member of the developer team to acknowledge the issue and provide more transparency.
As far as commons-el vs. jasper-el, does that mean that commons-el is only for JSP 2.0 and it won't be upgraded to support the Unified EL? What's the point of commons-el if Tomcat is providing their own implementation?
Charles - I'm not too concerned about someone hijacking my remember me cookie. However, I also know how to provide a better implementation than what Acegi provides. So if it ever gets hacked, I'll start writing that implementation. ;-)
Posted by Matt Raible on July 20, 2007 at 12:07 AM MDT #
Everything about that issue has been discussed on a public list - can't see how it can be any more transparent than that? In the past where we have been privately informed of vulnerabilities then we've kept quiet about it until we've had a fix version released. Theres two possible approaches to this 1) Warn everyone ASAP or 2) Publicize it as little as possible until a fix is available. The problem with 1) is that it also informs malicious users of how to attack sites built on Struts - something Struts Users may not appreciate when there isn't a fix available.
On commons-el vs. jasper-el - basically the Tomcat team got pissed off with Commons and have been in-housing components they used to depend on from Commons. Personally I don't agree with it - and don't understand why they didn't continue development in commons - a number of Tomcat devs. had access and I'm sure any others that wanted it would be welcomed. Its a policy I only becamse aware of early this year, and my attemt to lure them back didn't get any reaction. The good news is though that their Unified EL implementation is now available on the standard maven repo - thanks to Filip Hanik - so its available independantly of the rest of Tomcat. The bad news is that Jacob Hookom who donated the Unified EL impl to Tomcat has now abandonned it - taking it over to Glassfish and it doesn't look like anyone else from Tomcat has picked it up.
Posted by Niall on July 20, 2007 at 12:57 AM MDT #
While I agree that the default should be escaping, EL was likely designed with JSTL and its functions in mind:
But, it probably would be better if it had been the inverse:
Posted by Dave on July 20, 2007 at 04:47 AM MDT #
Posted by Jacob Hookom on July 20, 2007 at 05:51 AM MDT #
Posted by Janos Cserep on July 20, 2007 at 08:23 AM MDT #
Posted by Jacob Hookom on July 20, 2007 at 01:14 PM MDT #
Posted by Roshan Shrestha on July 20, 2007 at 02:54 PM MDT #
That's good to know Jacob. I like your decision. Do you think it's possible to lobby the Tomcat folks to allow a flag for jasper-el that provides the same behavior? All I'm looking for is something similar to trim spaces, which isn't part of the JSP spec AFAIK.
Roshan: Yes, Roller has some XSS issues when you have full HTML turned on for comments. I believe these are fixed in the 3.1 release (which I haven't upgraded to). Regardless, I still want full HTML functionality and since I get e-mail notifications for every comment - I'm not too concerned. I can delete the comment pretty quickly if it's malicious. However, it would be nice to auto-moderate comments with "script" in them, or something like that.
Posted by Matt Raible on July 20, 2007 at 03:35 PM MDT #
Posted by Jacob Hookom on July 20, 2007 at 03:43 PM MDT #
Posted by Bryan Noll on July 20, 2007 at 04:09 PM MDT #
Posted by Jacob Hookom on July 20, 2007 at 05:08 PM MDT #
Posted by Andreas Andreou on July 20, 2007 at 06:09 PM MDT #
Posted by Mark Helmstetter on July 22, 2007 at 06:24 AM MDT #
Posted by Zarar Siddiqi on November 15, 2007 at 05:13 PM MST #
Posted by Shoaib Akhtar on December 10, 2007 at 06:53 PM MST #
Posted by Matt Raible on December 10, 2007 at 10:54 PM MST #
Posted by Pete Nelson on May 30, 2008 at 01:30 AM MDT #
"The good news is #2 doesn't seem to be that hard. I pulled down commons-el yesterday, added a hack to escape XML, re-jarred and put it in Tomcat 5.0.25's classpath."
Hi Matt, I have struts problems with my app since it doesnt do anything for handling of XSS. I was wondering if you still have that jar file you fixed and re-jarred to make ${} to escape xml, and if I can have it to fix my application please.
Posted by Manny on October 15, 2009 at 09:13 PM MDT #
Posted by Matt Raible on October 16, 2009 at 03:21 AM MDT #
Posted by Manny on October 16, 2009 at 12:54 PM MDT #
Nice to hear that other developers use the same technique with us.
"Hack the jsp-compiler/el-engine to escape XML by default. "
Unfortunately, there is no other way for such a basic requirement.
There is only one, write a escapeThis(String) function and add it to every JSP expression, but this is not a good and clean solution.
We are using WebSphere and we had to touch JSP engine codes to escape HTML. Rarely you may need to bypass escaping, we did it by using a method like unescapeThis(String) in expressions and injecting this to the engine.
Another basic requirement is to ignore "null" string when displaying expressions. After 10 years, still JSP expressions prints null string to the page. I don't know how many developers want to see "null" in JSP pages. I'm sure 99.99 of JSP programmers don't want to see "null" string in page.
Posted by Ibrahim Levent on April 16, 2010 at 07:45 AM MDT #
Posted by Raible Designs on February 28, 2011 at 09:13 PM MST #