Bypassing servlet input validation filters (OWASP Stinger + Struts example)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~
0. ORIGINAL ADVISORY
~~~~~~~~~~~~~~~~~~~~
http://o0o.nu/~meder/o0o_bypassing_servlet_input_validation_filters.txt
I. BACKGROUND
~~~~~~~~~~~~~
NOTE: This advisory will use OWASP's Stinger and Struts framework to
illustrate the concept, however this technique should be applicable to
other input validation servlet filters that do not handle multipart
requests properly and frameworks that automatically parse multipart
requests.
Java Servlets provide a filter component which can dynamically intercept
requests and responses to transform information contained in the
requests or responses[1]. Servlet filters are often recommended as an
effective way to perform input validation in Java web applications due
to the centralized nature and little modifications required to the
application's code.
Open Web Application Security Project (OWASP) has developed Stinger,
which aims to provide a centralized input validation component which can
be easily applied to existing or developmental applications[4].
There is a vulnerability in servlet filters, such as the Stinger filter,
which under certain conditions will allow attacker to bypass input
validation routines of the filter thus supplying unvalidated input to
the application, potentially exploiting vulnerabilities, such as XSS or
SQL injection.
II. DESCRIPTION
~~~~~~~~~~~~~~~
OWASP Stinger is built with the assumption that content of requests passing
through it are always form-urlencoded. This assumption is harmless in a
simple J2EE web application setup as both Stinger and application will
use the same methods to access HTTP parameters (i.e. Request.getParameter()
or Request.getParameterNames()[3]). However, in an application that uses
frameworks that abstract HTTP protocol and provide automatic request
handling/parsing, this assumption can result in the ability to bypass
Stinger filtering while still delivering inputs to the target application.
The following Stinger code snippet illustrates the problem (Stinger.java):
private int checkMalformedParameters(...) {
...
e = request.getParameterNames();
while(e.hasMoreElements()) {
...
}
...
}
If HTTP request content was form-urlencoded then request.getParameterNames()
will return Enumeration of all HTTP parameters names. However, if the request
is multipart encoded, Enumeration that is returned will be empty and
e.hasMoreElements() will return false, which in turn will result in
Stinger not performing any input validation on the multipart encoded HTTP
requests. It should be noted that standard servlet API doesn't provide a
convenient way of handling multipart requests.
If the target application is a plain vanilla servlet application,
multipart encoded HTTP parameters will not be returned by the
Request.getParameter() call and thus input will not be honored by the
target application. However, frameworks like Struts abstract HTTP
details from the application and perform automatic parsing of HTTP
requests, including multipart encoded requests. The framework will then
pass the input parameters supplied in a multipart request to the
application, which will be unaware whether parameters came in through a
multipart request or a regular form-urlencoded request. And as Stinger
did not perform any validation on the multipart request, unescaped and
unvalidated data will be supplied to the application, which in turn may
result in a security vulnerability such as XSS or SQL injection being
exploited.
III. Testing
~~~~~~~~~~~~
Following WebScarab beanshell script can be used test existing servlet
filter implementations:
http://o0o.nu/~meder/toolz/Multipartify.txt
IV. RECOMMENDATIONS
~~~~~~~~~~~~~~~~~~~~
Servlet filters should handle multipart requests and perform input
validation on the multipart encoded content.
Additionally, following the multi-layered security approach,
applications should not rely on the filter to provide input validation
and be the only line of defense. Most of the frameworks today provide
a way to perform input validation within the application [5,6].
Also, if multipart requests are not required by the application (e.g.
no file uploads are performed) automatic handling of multipart requests
should be disabled in the framework and servlet filter could be
configured to drop multipart requests.
V. VENDOR STATUS
~~~~~~~~~~~~~~~~
OWASP Stinger 2.5 contains a quick fix to drop non-urlencoded requests.
VI. DISCLOSURE TIMELINE
~~~~~~~~~~~~~~~~~~~~~~~
18/07/2007 - Vulnerability details sent to the maintainer
23/07/2007 - Vulnerability details resent
26/07/2007 - Initial vendor response (delay due to spam filters)
05/08/2007 - Quick-fix implemented dropping multipart requests in
Stinger 2.5
VII. ACKNOWLEDGEMENTS
~~~~~~~~~~~~~~~~~~~~~
blshkv, jml for helping to verify the issue. Rogan Dawes and Jeff
Williams for helping to get in contact with maintainer. Eric Sheridan
for a timely resolution of the issue.
VIII. REFERENCES
~~~~~~~~~~~~~~~~
1. "The Essentials of Filters", http://java.sun.com/products/servlet/Filters.html
2. "Form-based File Upload in HTML", http://www.ietf.org/rfc/rfc1867.txt
3. "Interface ServletRequest",
http://java.sun.com/j2ee/1.4/docs/api/javax/servlet/ServletRequest.html
4. "OWASP Stinger Project",
http://www.owasp.org/index.php/Category:OWASP_Stinger_Project
5. "Struts Validator", http://struts.apache.org/1.3.8/faqs/validator.html
6. "Validation", http://struts.apache.org/2.x/docs/validation.html