442 lines
18 KiB
Diff
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());
|
|
+
|
|
+ }
|
|
+
|
|
}
|