struts/struts-1.3.10-CVE-2015-0899.patch
2020-08-25 14:19:57 +08:00

442 lines
18 KiB
Diff

diff -Nru struts-1.3.10/src/core/pom.xml struts-1.3.10.CVE-2015-0899/src/core/pom.xml
--- struts-1.3.10/src/core/pom.xml 2015-03-30 12:13:30.943199760 +0200
+++ struts-1.3.10.CVE-2015-0899/src/core/pom.xml 2015-03-30 12:40:00.302267718 +0200
@@ -184,6 +184,12 @@
<artifactId>oro</artifactId>
<version>2.0.8</version>
</dependency>
+ <dependency>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ <version>1.2.17</version>
+ <scope>test</scope>
+ </dependency>
</dependencies>
</project>
diff -Nru struts-1.3.10/src/core/src/main/java/org/apache/struts/config/ActionConfig.java struts-1.3.10.CVE-2015-0899/src/core/src/main/java/org/apache/struts/config/ActionConfig.java
--- struts-1.3.10/src/core/src/main/java/org/apache/struts/config/ActionConfig.java 2008-06-05 00:13:42.000000000 +0200
+++ struts-1.3.10.CVE-2015-0899/src/core/src/main/java/org/apache/struts/config/ActionConfig.java 2015-03-30 12:20:14.202124216 +0200
@@ -861,6 +861,36 @@
}
}
+ // 2014/07/02 - security problem patch.
+ // Author: NTT DATA Corporation
+ /**
+ * Accepted page value for multi-page validation.<br>
+ * If two or more page values are accepted, then acceptPage is set minimum of them.<br>
+ * If multi-page validation is not use, acceptPage is not set. Then multi-page validation is disabled.
+ * @since Struts 1.2.9-sp2
+ */
+ protected Integer acceptPage = null;
+
+ /**
+ * Returns accepted page value for multi-page validation.
+ *
+ * @return Accepted page value for multi-page validation
+ * @since Struts 1.2.9-sp2
+ */
+ public Integer getAcceptPage() {
+ return acceptPage;
+ }
+
+ /**
+ * Set accepted page value for multi-page validation.
+ *
+ * @param acceptPage Accepted page value for multi-page validation
+ * @since Struts 1.2.9-sp2
+ */
+ public void setAcceptPage(Integer acceptPage) {
+ this.acceptPage = acceptPage;
+ }
+
// --------------------------------------------------------- Public Methods
/**
@@ -1283,6 +1313,11 @@
sb.append(type);
}
+ // 2014/07/02 - security problem patch.
+ // Author: NTT DATA Corporation
+ sb.append(",acceptPage=");
+ sb.append(acceptPage);
+
return (sb.toString());
}
}
diff -Nru struts-1.3.10/src/core/src/main/java/org/apache/struts/util/RequestUtils.java struts-1.3.10.CVE-2015-0899/src/core/src/main/java/org/apache/struts/util/RequestUtils.java
--- struts-1.3.10/src/core/src/main/java/org/apache/struts/util/RequestUtils.java 2015-03-30 12:13:31.002196823 +0200
+++ struts-1.3.10.CVE-2015-0899/src/core/src/main/java/org/apache/struts/util/RequestUtils.java 2015-03-30 12:23:40.352806356 +0200
@@ -469,6 +469,14 @@
parameterValue = request.getParameterValues(name);
}
+ // 2014/05/13 - CVE-2014-0114 security problem patch.
+ // Author: NTT DATA Corporation
+ if (stripped.startsWith("class.") || stripped.indexOf(".class.") >= 0) {
+ // this log output is only for detection of invalid parameters and not an integral part of the bug fix
+ log.info("ignore parameter: paramName=" + stripped);
+ continue;
+ }
+
// Populate parameters, except "standard" struts attributes
// such as 'org.apache.struts.action.CANCEL'
if (!(stripped.startsWith("org.apache.struts."))
diff -Nru struts-1.3.10/src/core/src/main/java/org/apache/struts/validator/DynaValidatorForm.java struts-1.3.10.CVE-2015-0899/src/core/src/main/java/org/apache/struts/validator/DynaValidatorForm.java
--- struts-1.3.10/src/core/src/main/java/org/apache/struts/validator/DynaValidatorForm.java 2008-06-05 00:14:02.000000000 +0200
+++ struts-1.3.10.CVE-2015-0899/src/core/src/main/java/org/apache/struts/validator/DynaValidatorForm.java 2015-03-30 12:22:30.733325776 +0200
@@ -112,9 +112,12 @@
String validationKey = getValidationKey(mapping, request);
+ // 2014/07/02 - security problem patch.
+ // Author: NTT DATA Corporation
+ int validationPage = determinePage(mapping, request);
Validator validator =
Resources.initValidator(validationKey, this, application, request,
- errors, page);
+ errors, validationPage);
try {
validatorResults = validator.validate();
@@ -125,6 +128,24 @@
return errors;
}
+ // 2014/07/02 - security problem patch.
+ // Author: NTT DATA Corporation
+ /**
+ * Determine validation page.<br>
+ * If acceptPage of ActionMapping is null, then returns Integer.MAX_VALUE.
+ * (multi-page validation is disabled. All validation fields are enabled.)<br>
+ * If page property is less than acceptPage of ActionMapping, returns acceptPage value.<br>
+ * If page property is greater than or equal to acceptPage of ActionMapping, returns page property value.
+ * @param mapping The mapping used to select this instance.
+ * @param request The servlet request we are processing.
+ * @return validation page.
+ * @since Struts 1.2.9-sp2
+ */
+ protected int determinePage(ActionMapping mapping, HttpServletRequest request) {
+ Integer acceptPage = mapping.getAcceptPage();
+ return acceptPage != null ? Math.max(acceptPage.intValue(), page) : Integer.MAX_VALUE;
+ }
+
/**
* Returns the Validation key.
*
diff -Nru struts-1.3.10/src/core/src/main/java/org/apache/struts/validator/ValidatorForm.java struts-1.3.10.CVE-2015-0899/src/core/src/main/java/org/apache/struts/validator/ValidatorForm.java
--- struts-1.3.10/src/core/src/main/java/org/apache/struts/validator/ValidatorForm.java 2008-06-05 00:14:02.000000000 +0200
+++ struts-1.3.10.CVE-2015-0899/src/core/src/main/java/org/apache/struts/validator/ValidatorForm.java 2015-03-30 12:36:22.312287599 +0200
@@ -108,9 +108,12 @@
String validationKey = getValidationKey(mapping, request);
+ // 2014/07/02 - security problem patch.
+ // Author: NTT DATA Corporation
+ int validationPage = determinePage(mapping, request);
Validator validator =
Resources.initValidator(validationKey, this, application, request,
- errors, page);
+ errors, validationPage);
try {
validatorResults = validator.validate();
@@ -121,6 +124,24 @@
return errors;
}
+ // 2014/07/02 - security problem patch.
+ // Author: NTT DATA Corporation
+ /**
+ * Determine validation page.<br>
+ * If acceptPage of ActionMapping is null, then returns Integer.MAX_VALUE.
+ * (multi-page validation is disabled. All validation fields are enabled.)<br>
+ * If page property is less than acceptPage of ActionMapping, returns acceptPage value.<br>
+ * If page property is greater than or equal to acceptPage of ActionMapping, returns page property value.
+ * @param mapping The mapping used to select this instance.
+ * @param request The servlet request we are processing.
+ * @return validation page.
+ * @since Struts 1.2.9-sp2
+ */
+ protected int determinePage(ActionMapping mapping, HttpServletRequest request) {
+ Integer acceptPage = mapping.getAcceptPage();
+ return acceptPage != null ? Math.max(acceptPage.intValue(), page) : Integer.MAX_VALUE;
+ }
+
/**
* Returns the Validation key.
*
diff -Nru struts-1.3.10/src/core/src/test/java/org/apache/struts/util/TestRequestUtilsPopulate.java struts-1.3.10.CVE-2015-0899/src/core/src/test/java/org/apache/struts/util/TestRequestUtilsPopulate.java
--- struts-1.3.10/src/core/src/test/java/org/apache/struts/util/TestRequestUtilsPopulate.java 2015-03-30 12:13:30.984197719 +0200
+++ struts-1.3.10.CVE-2015-0899/src/core/src/test/java/org/apache/struts/util/TestRequestUtilsPopulate.java 2015-03-30 12:33:30.592968395 +0200
@@ -21,11 +21,19 @@
package org.apache.struts.util;
+import java.io.BufferedReader;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.util.HashSet;
+
import javax.servlet.ServletException;
import junit.framework.Test;
import junit.framework.TestSuite;
+import org.apache.log4j.LogManager;
+import org.apache.log4j.PatternLayout;
+import org.apache.log4j.WriterAppender;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.util.RequestUtils;
import org.apache.struts.Globals;
@@ -120,4 +128,247 @@
}
+ /**
+ * Ensure that the parameter of HTTP request
+ * which causes ClassLoader manipulation is ignored.
+ *
+ * The purpose of this test is to ensure that security problem
+ * CVE-2014-0114 is fixed.
+ *
+ */
+ public void testRequestParameterIgnore1() throws Exception {
+
+ String stringValue = "Test";
+
+ MockFormBean mockForm = new MockFormBean();
+
+ // Set up the mock HttpServletRequest
+ request.setMethod("GET");
+ request.setContentType("");
+
+ request.addParameter("class.xxx.case1", stringValue);
+
+ // logger
+ StringWriter writer = new StringWriter();
+ WriterAppender appender = new WriterAppender(new PatternLayout("%p, %m%n"), writer);
+ LogManager.getRootLogger().addAppender(appender);
+ LogManager.getRootLogger().setAdditivity(false);
+
+ // Try to populate
+ HashSet ignoreSet = new HashSet();
+ try {
+ RequestUtils.populate(mockForm, request);
+
+ String keyword1 = "INFO, ";
+ String keyword2 = "ignore parameter: paramName=";
+ String logString = writer.toString();
+ StringReader reader = new StringReader(logString);
+ BufferedReader bufReader = new BufferedReader(reader);
+ String line = null;
+ while ((line = bufReader.readLine()) != null) {
+ if (!line.startsWith(keyword1)) {
+ continue;
+ }
+ int pos = line.indexOf(keyword2);
+ if (pos >= 0) {
+ ignoreSet.add(line.substring(pos + keyword2.length()));
+ }
+ }
+ } catch(ServletException se) {
+ fail("Occur exception.");
+ } finally {
+ LogManager.getRootLogger().removeAppender(appender);
+ LogManager.getRootLogger().setAdditivity(true);
+ }
+
+ // Check
+ assertEquals("ignore num no match", 1, ignoreSet.size());
+ assertTrue("not exists ignore parameter class.xxx.case1", ignoreSet.contains("class.xxx.case1"));
+ assertNull("ActionForm property set", mockForm.getStringProperty());
+
+ }
+
+ /**
+ * Ensure that the parameter of HTTP request
+ * which causes ClassLoader manipulation is ignored.
+ *
+ * The purpose of this test is to ensure that security problem
+ * CVE-2014-0114 is fixed.
+ *
+ */
+ public void testRequestParameterIgnore2() throws Exception {
+
+ String stringValue = "Test";
+
+ MockFormBean mockForm = new MockFormBean();
+
+ // Set up the mock HttpServletRequest
+ request.setMethod("GET");
+ request.setContentType("");
+
+ request.addParameter("xxx.class.case2", stringValue);
+
+ // logger
+ StringWriter writer = new StringWriter();
+ WriterAppender appender = new WriterAppender(new PatternLayout("%p, %m%n"), writer);
+ LogManager.getRootLogger().addAppender(appender);
+ LogManager.getRootLogger().setAdditivity(false);
+
+ // Try to populate
+ HashSet ignoreSet = new HashSet();
+ try {
+ RequestUtils.populate(mockForm, request);
+
+ String keyword1 = "INFO, ";
+ String keyword2 = "ignore parameter: paramName=";
+ String logString = writer.toString();
+ StringReader reader = new StringReader(logString);
+ BufferedReader bufReader = new BufferedReader(reader);
+ String line = null;
+ while ((line = bufReader.readLine()) != null) {
+ if (!line.startsWith(keyword1)) {
+ continue;
+ }
+ int pos = line.indexOf(keyword2);
+ if (pos >= 0) {
+ ignoreSet.add(line.substring(pos + keyword2.length()));
+ }
+ }
+ } catch(ServletException se) {
+ fail("Occur exception.");
+ } finally {
+ LogManager.getRootLogger().removeAppender(appender);
+ LogManager.getRootLogger().setAdditivity(true);
+ }
+
+ // Check
+ assertEquals("ignore num no match", 1, ignoreSet.size());
+ assertTrue("not exists ignore parameter xxx.class.case2", ignoreSet.contains("xxx.class.case2"));
+ assertNull("ActionForm property set", mockForm.getStringProperty());
+
+ }
+
+ /**
+ * Ensure that the parameter of HTTP request
+ * which causes ClassLoader manipulation is ignored.
+ *
+ * The purpose of this test is to ensure that security problem
+ * CVE-2014-0114 is fixed.
+ *
+ */
+ public void testRequestParameterIgnore3() throws Exception {
+
+ String stringValue = "Test";
+
+ MockFormBean mockForm = new MockFormBean();
+
+ // Set up the mock HttpServletRequest
+ request.setMethod("GET");
+ request.setContentType("");
+
+ request.addParameter("stringProperty", stringValue);
+
+ // logger
+ StringWriter writer = new StringWriter();
+ WriterAppender appender = new WriterAppender(new PatternLayout("%p, %m%n"), writer);
+ LogManager.getRootLogger().addAppender(appender);
+ LogManager.getRootLogger().setAdditivity(false);
+
+ // Try to populate
+ HashSet ignoreSet = new HashSet();
+ try {
+ RequestUtils.populate(mockForm, request);
+
+ String keyword1 = "INFO, ";
+ String keyword2 = "ignore parameter: paramName=";
+ String logString = writer.toString();
+ StringReader reader = new StringReader(logString);
+ BufferedReader bufReader = new BufferedReader(reader);
+ String line = null;
+ while ((line = bufReader.readLine()) != null) {
+ if (!line.startsWith(keyword1)) {
+ continue;
+ }
+ int pos = line.indexOf(keyword2);
+ if (pos >= 0) {
+ ignoreSet.add(line.substring(pos + keyword2.length()));
+ }
+ }
+ } catch(ServletException se) {
+ fail("Occur exception.");
+ } finally {
+ LogManager.getRootLogger().removeAppender(appender);
+ LogManager.getRootLogger().setAdditivity(true);
+ }
+
+ // Check
+ assertEquals("ignore num no match", 0, ignoreSet.size());
+ assertFalse("exists ignore parameter stringProperty", ignoreSet.contains("stringProperty"));
+ assertEquals("ActionForm property not equal", stringValue, mockForm.getStringProperty());
+
+ }
+
+ /**
+ * Ensure that the parameter of HTTP request
+ * which causes ClassLoader manipulation is ignored.
+ *
+ * The purpose of this test is to ensure that security problem
+ * CVE-2014-0114 is fixed.
+ *
+ */
+ public void testRequestParameterIgnore4() throws Exception {
+
+ String stringValue = "Test";
+
+ MockFormBean mockForm = new MockFormBean();
+
+ // Set up the mock HttpServletRequest
+ request.setMethod("GET");
+ request.setContentType("");
+
+ request.addParameter("class.xxx.case4", stringValue);
+ request.addParameter("xxx.class.case4", stringValue);
+ request.addParameter("stringProperty", stringValue);
+
+ // logger
+ StringWriter writer = new StringWriter();
+ WriterAppender appender = new WriterAppender(new PatternLayout("%p, %m%n"), writer);
+ LogManager.getRootLogger().addAppender(appender);
+ LogManager.getRootLogger().setAdditivity(false);
+
+ // Try to populate
+ HashSet ignoreSet = new HashSet();
+ try {
+ RequestUtils.populate(mockForm, request);
+
+ String keyword1 = "INFO, ";
+ String keyword2 = "ignore parameter: paramName=";
+ String logString = writer.toString();
+ StringReader reader = new StringReader(logString);
+ BufferedReader bufReader = new BufferedReader(reader);
+ String line = null;
+ while ((line = bufReader.readLine()) != null) {
+ if (!line.startsWith(keyword1)) {
+ continue;
+ }
+ int pos = line.indexOf(keyword2);
+ if (pos >= 0) {
+ ignoreSet.add(line.substring(pos + keyword2.length()));
+ }
+ }
+ } catch(ServletException se) {
+ fail("Occur exception.");
+ } finally {
+ LogManager.getRootLogger().removeAppender(appender);
+ LogManager.getRootLogger().setAdditivity(true);
+ }
+
+ // Check
+ assertEquals("ignore num no match", 2, ignoreSet.size());
+ assertTrue("not exists ignore parameter class.xxx.case4", ignoreSet.contains("class.xxx.case4"));
+ assertTrue("not exists ignore parameter xxx.class.case4", ignoreSet.contains("xxx.class.case4"));
+ assertEquals("ActionForm property not equal", stringValue, mockForm.getStringProperty());
+
+ }
+
}