Apache Struts 1 is a popularly used JAVA EE web application framework. It offers many kinds of validators to filter user input by using the Apache Common Validator library, which is both convenient and fast. However, a bug in Apache Struts can be used to easily bypass the input validation process, allowing an attacker to submit arbitrary dirty data to the database, possibly resulting in a cross-site scripting attack when the user views the JSP file that refers directly to the corrupted data.
This potential Input Validation Bypass vulnerability is caused by an error in both ValidatorForm.java and DynaValidatorForm.java when initializing the validator, and it will not be fixed in Apache Struts 1 since Apache Struts 1 is End-Of-Life. In this post we will analyze the Apache Struts source codes and expose the root cause of this vulnerability.
ValidatorForm.java and DynaValidatorForm.java define the ValidatorForm class and the DynaValidatorForm class, which extend the ActionForm class. These two classes override the validate() function to validate user input by calling the validation methods implemented in the Apache Struts Common Validator library. They have a property "page" which is used to indicate the current page number of a multiple page form. The value of the "page" is read from the HTTP POST request generated by the JSP file from the client. At the same time, every field in a form that needs to be validated has a "page" property as well, which is defined in the configuration file "validation.xml". When a specific field in a form needs to be validated, the validator only performs its function when the "page" value of the ValidatorForm class or DynaValidatorForm class is greater than the "page" value of the field. If an attacker sends a "page" with a value less than the "page" value of the field, the validator will skip the validation, thereby allowing input validation bypass to occur.
The following code snippet was taken from Apache Struts 1 1.2.9 and Apache struts Common Validator 1.6. Comments added by me have been highlighted.
We use the following struts ValidatorForm example to show how the input validation bypass works. In this example, we define an EmployeeForm class which extends the ValidatorForm class.
From the above, we can see that the "username" field should not be null and its length should be between 3 and 100, and that can only be a word, number, dash, or underscore. The following image shows the normal condition when input validation works:
We used the following "success.jsp" to show the username after bypassing input validation. "success.jsp" just gets the "username" property from the javabean and displays it.
Finally, when we modify the HTTP POST request manually and set the malicious "page" value, the following netcat result shows the returned web content generated by " success.jsp".
Please note that authentication is NOT required to exploit this vulnerability.
Fortinet released IPS signature Apache.Struts.MPV.Input.Validation.Bypass to address this vulnerability.