Monday, September 13, 2010

Danger of JSP Includes and Parameter Passing

I just recently built a JSP application to demonstrate the capabilities of AppSensor and ESAPI.  I decided to use strictly JSPs to keep the code relatively simple and easy to use as a reference for AppSensor ideas.  During the development of this app I discovered an interesting (and concerning) behavior of JSP include tags.

Consider the following design where JSP includes are used to maximize code reusability. For each lesson the lessonIdentifier and lessonName are defined at the top of the lessonX.jsp file and then those values are passed to "preContent.jsp" which displays a bunch of info in the final jsp that is constructed.
lesson1.jsp

<%@include file="header.jsp"%>
<%
    String lessonIdentifier="1";
    String lessonName="lesson 1 - attack detection";
    String lessonObjective="Do something";   
%>

<jsp:include page="WEB-INF/preContent.jsp">
    <jsp:param name="lessonIdentifier" value="<%=lessonIdentifier%>"/>
    <jsp:param name="lessonName" value="<%=lessonName%>"/>
    <jsp:param name="lessonObjective" value="<%=lessonObjective%>"/>
</jsp:include>

More JSP/html content here.

<%@include file="footer.jsp"%>



WEB-INF/preContet.jsp


<div id="lessonTitle">
<b>Lesson:</b><br/> <%=request.getParameter(lessonName)%><br />
<b>Objective:</b><br/> <%=request.getParameter(lessonObjective)%>
</div>


preContent.jsp is located within the WEB-INF folder and cannot be directly requested by a user. The only way the lesson name could be passed to this jsp is through the jsp:include from lesson1.jsp.  So in the above scenario everything works great and there is no XSS concern.

However, take a look at lesson2.jsp below. Its the same as lesson1.jsp but the author forget to define the lessonName and lessonObjective variables and also did not include them as parameters for the jsp include statement.
lesson2.jsp

<%@include file="header.jsp"%>
<%
    String lessonIdentifier="2";
    //String lessonName="xxx";
    //String lessonObjective="xxx";
%>

<jsp:include page="WEB-INF/preContent.jsp">
    <jsp:param name="lessonIdentifier" value="<%=lessonIdentifier%>"/>
</jsp:include>

More JSP/html content here.

<%@include file="footer.jsp"%>

Now we have a scenario where lesson2.jsp still includes the preContent.jsp from WEB-INF but has forgotten to pass the lessonName and lessonObjective variables.  The code still works and no errors are thrown.  This is a problem because we have now introduced a huge XSS issue.  The preContent.jsp did not receive the parameters during the <jsp:include>; however, instead of displaying a null value or even throwing an error message, the reqeust.getParameter simply fails over and looks for a URL argument.

An attacker with knowledge of the source code could make the following malicious request

http://somesite.com/lesson2.jsp?lessonName=<script>alert('xss fun')</script>

Resulting Processing by the JSP:
1: lesson2.jsp includes WEB-INF/preContent.jsp
2. preContent.jsp was not given the lessonName parameter from the jsp:include and looks to the URL
3. preContent.jsp finds the URL argument and dangerously includes the user controlled data

It should be noted that the same attack on lesson1.jsp is not exploitable since the preContent.jsp finds the lessonName parameter from lesson1.jsp as part of step 2 in the process.


Conclusions

I'm very concerned by the overloaded behavior of parameter passing. In my opinion the call to request parameters from a jsp include should be different from the call to get parameters from GET or POST statements.  With these changes the above scenario would not be vulnerable and would also result in a run time error indicating that the jsp include did not send the expected parameters.  The current "fail-over" type behavior of reqeust.getParameter is not expected and can result in dangerous XSS vulnerabilities as indicated above.


I am interested in feedback from experienced JSP developers. How do you structure your code with JSP includes? Is this a plausible scenario in your opinion or have I just identified a poorly architected edge case scenario?


-Michael Coates