Tuesday, May 10, 2011

Apache Struts 2, XWork, WebWork ... Reflected XSS Vulnerabilities



The recently released Apache Struts 2.2.3 framework includes fixes for two reflected XSS vulnerabilities.


User provided data is not
properly escaped before being included in XWork generated errors, thus allowing successful reflected XSS attacks as described in MVSA-11-006 security advisory.

NOTE: Other open source projects and commercial products relying on XWork framework could be vulnerable to attacks similar to the ones described in this post.


NOTE:
WebWork framework released by OpenSymphony (http://opensymphony.org) was already confirmed as vulnerable to reflected XSS attacks using similar vectors.


1. XSS payload injected in the name of the requested Struts actions


Preconditions:

  • no declarative error handling rule is defined in struts.xml using <global-exception-mappings> tag
Test case:

http://test.app1.net/login%3Cimg%3E.action

HTML source code for the error displayed (HTTP response Content-Type is text/html):

There is no Action mapped for namespace / and action name login<img>.


This allows successful reflected XSS attacks by injecting malicious scripting code into the name of requested Struts actions.


2. Reflected XSS vulnerabilities in with DMI enabled


Preconditions:

  • no declarative error handling rule is defined in struts.xml using tag
  • Dynamic Method Invocation is enabled (this is enabled by default)
  • bash syntax is used in JSP via tag for calling Struts actions and methods
  • the requested method is not matching an existing one already defined in the Struts action implementation class
  • the requested action is not matching an existing one already defined in struts.xml
Example of <s:submit> tag usage with JSP:

<body>
...
<form name="loginform" id="loginform" method="post" action="">
...
<s:submit action="login" method="cantLogin" name="cantlogin" key="cantlogin" />
...
</form>
...
</body>


2.1 Test case - XSS payload is injected in action attribute of
<s:submit> tag

http://test.app.net/home.html?user=&password=
&action!login%3cscript%3ealert(document.cookie)%3c/script%3e:cantLogin=some_name

HTML source code for the error displayed (HTTP response Content-Type is text/html):

There is no Action mapped for namespace / and action name login<script>alert(document.cookie)</script>.


NOTE: Without proper output escaping for the invoked action (which is controlled by the user), the injected malicious scripting code is executed by the browser (the HTTP response's content-type header is set to text/html).

This allows successful reflected XSS attacks using <s:submit> tag.


2.2 Test case - XSS payload is injected in method attribute of
<s:submit> tag

http://test.app.net/home.html?user=&password=&action!login:cantLogin
%3cscript%3ealert(document.cookie)%3c/script%3e=some_name

HTML source code for the error displayed (HTTP response Content-Type is text/html):

some_path.action.LoginAction.cantLogin<script>alert(document.cookie)</script>()

NOTE: Without proper output escaping for the invoked method (which is controlled by the user), the injected scripting code will be executed by the browser (the HTTP response's content-type header is set to text/html).

This allows successful reflected XSS attacks using <s:submit> tag.

UPDATED (2011-05-18): The returned error also exposes internal paths for the Java class implementing the action for which we manipulate the method to be called (LoginAction in this case).
This issue is documented by MVSA-11-007 security advisory.

WebWork framework seems to be vulnerable to similar attacks. However, since the project is not actively maintained (being replaced by Apache Struts 2), there might be an option to look into building the project from source and to include similar fixes to those suggested for XWork
com.opensymphony.xwork2.DefaultActionProxy class patched in Struts 2.2.3 (details available at https://issues.apache.org/jira/browse/WW-3579).