Overview
Apache Struts is a popular open-source web application framework for developing Java EE web applications. It provides robust support for creating modern Java-based enterprise applications.
An Authorization Bypass vulnerability (CVE-2015-0899) has been identified in Apache Struts, which allows attackers to execute arbitrary code on the target system by sending specially crafted requests. This can compromise system integrity and lead to further exploitation.
Authorization Bypass occurs when an application fails to properly enforce user permissions, allowing attackers to access restricted functionalities or data without proper authorization.
This issue affects multiple versions >=1.1.0 <=1.3.10
Details
Module Info
- Product: Apache Struts 1
- Affected packages: struts-core
- Affected versions: >=1.1.0 <=1.3.10
- GitHub repository: https://github.com/apache/struts1
- Package manager: Maven
- Fixed in: NES for Struts Struts 1 v1.3.11
Vulnerability Info
Apache Struts 1 Validator’s Multi-Page Validator (MPV) feature, which contains a flaw that may allow input validation rules to be bypassed. Even if an application does not explicitly use MPV, the underlying weakness in the Struts 1 Validator could still expose the web application to unauthorized actions. This could enable attackers to submit manipulated requests, circumvent security controls, and potentially gain access to protected resources, modify data, or exploit the system in unintended ways. Proper validation and access control mechanisms are essential to mitigating this type of vulnerability.
Steps To Reproduce
Step 1: Enable Validator Plugin in struts-config.xml
<plug-in className="org.apache.struts.validator.ValidatorPlugIn">
<set-property property="pathnames" value="/WEB-INF/validator-rules.xml, /WEB-INF/validation.xml"/>
</plug-in>
Step 2: Define Multi-Page Validation in validation.xml
<formset>
<form name="/step1">
<!-- Validation rules for Page 1 -->
<field property="age" depends="required, intRange, integer">
<arg key="exampleForm.age"/>
<arg name="intRange" key="${var:min}" resource="false" />
<arg name="intRange" key="${var:max}" resource="false" />
<var>
<var-name>min</var-name>
<var-value>18</var-value>
</var>
<var>
<var-name>max</var-name>
<var-value>90</var-value>
</var>
</field>
<field property="email" depends="required,email">
<arg key="exampleForm.email" />
</field>
</form>
<form name="/step2">
<field property="city" depends="required, minlength">
<arg key="exampleForm.city" />
<arg key="${var:minlength}" resource="false" />
<var>
<var-name>minlength</var-name>
<var-value>2</var-value>
</var>
</field>
</formset>
Step 3: Define Action Form (ExampleForm.java)
public class ExampleForm extends ValidatorActionForm{
// properties
String email;
Integer age;
String city;
// getter and setter methods
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
}
Step 4: Configure Action Mapping in struts-config.xml
<action
attribute="exampleForm"
input="/form/step1.jsp"
name="exampleForm"
path="/step1"
scope="request"
type="org.apache.struts.apps.multipageform.action.Step1" >
<forward name="step1" path="/form/step1.jsp" />
<forward name="step2" path="/step2.do" />
</action>
<action
attribute="exampleForm"
input="/form/step2.jsp"
name="exampleForm"
path="/step2"
scope="request"
type="org.apache.struts.apps.multipageform.action.Step2" >
<forward name="step2" path="/form/step2.jsp" />
<forward name="finish" path="/finish.do" />
</action>
<action
attribute="exampleForm"
input="/form/finish.jsp"
name="exampleForm"
path="/finish"
scope="request"
type="org.apache.struts.apps.multipageform.action.Finish" >
<forward name="finish" path="/form/finish.jsp" />
</action>
Step 5: Create JSP Pages (step1.jsp & step2.jsp & finish.jsp) like the following step1.jsp
<%@ page language="java"%>
<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean"%>
<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html"%>
<html>
<head>
<title>Step 1</title>
</head>
<body>
<html:form action="/step1">
<%-- ouput errors --%>
<html:messages id="error" message="false">
<bean:write name="error" /> <br />
</html:messages>
<%-- input field for properties --%>
Email: <html:text property="email" /> <br />
Age: <html:text property="age" /> <br />
<%-- hidden field which specify the page --%>
<html:hidden property="step" value="1" />
<html:submit property="btnStep1"/>
</html:form>
</body>
</html>
Step 6: Implement Action Classes
package org.apache.struts.apps.multipageform.action;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
public class Step1 extends Action {
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request,
HttpServletResponse response) throws Exception {
String forward = "step1";
if(request.getParameter("btnStep1") != null){
forward = "step2";
}
return mapping.findForward(forward);
}
}
Step 7: Deploy and Test
- Deploy the application to a Servlet container (like Apache Tomcat).
- Navigate to /step1.jsp and fill in age and email, then click Next. Validate fails on incorrect age.
Step 9: Bypass
- POST request to /step1.do
- Include page=-1 and age=17 and email=email@email.com in request body
- The output will result as success with invalid age
Mitigation
Struts 1 is no longer community-supported. The community support version will not receive any updates to address this issue. For more information, see here.
Users of the affected components should apply one of the following mitigations:
- Upgrade affected applications to supported versions of Struts
Leverage a commercial support partner like HeroDevs for post-EOL security support.