gil pushed to struts (master). "fix CVE-2015-0899 (rhbz#1207099)"
notifications at fedoraproject.org
notifications at fedoraproject.org
Mon Mar 30 10:50:59 UTC 2015
>From 5f83bd9f5d94ea6dd621748a5c637eef2699eb33 Mon Sep 17 00:00:00 2001
From: gil <puntogil at libero.it>
Date: Mon, 30 Mar 2015 12:50:36 +0200
Subject: fix CVE-2015-0899 (rhbz#1207099)
diff --git a/struts-1.3.10-CVE-2015-0899.patch b/struts-1.3.10-CVE-2015-0899.patch
new file mode 100644
index 0000000..a4129cf
--- /dev/null
+++ b/struts-1.3.10-CVE-2015-0899.patch
@@ -0,0 +1,441 @@
+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());
++
++ }
++
+ }
diff --git a/struts.spec b/struts.spec
index 8f223e5..55b45c6 100644
--- a/struts.spec
+++ b/struts.spec
@@ -1,7 +1,7 @@
%global master_version 4
Name: struts
Version: 1.3.10
-Release: 13%{?dist}
+Release: 14%{?dist}
Summary: Web application framework
License: ASL 2.0
URL: http://struts.apache.org/
@@ -32,6 +32,8 @@ Patch1: %{name}-%{version}-jboss.patch
# and Brandon.Vincent at asu.edu
Patch2: struts-1.3.10-CVE-2014-0114.patch
+Patch3: struts-1.3.10-CVE-2015-0899.patch
+
BuildRequires: mvn(antlr:antlr)
BuildRequires: mvn(commons-beanutils:commons-beanutils)
BuildRequires: mvn(commons-chain:commons-chain)
@@ -40,6 +42,11 @@ BuildRequires: mvn(commons-fileupload:commons-fileupload)
BuildRequires: mvn(commons-logging:commons-logging)
BuildRequires: mvn(commons-validator:commons-validator)
BuildRequires: mvn(junit:junit)
+%if %{?fedora} >= 21
+BuildRequires: mvn(log4j:log4j:1.2.17)
+%else
+BuildRequires: mvn(log4j:log4j)
+%endif
BuildRequires: mvn(org.apache.bsf:bsf)
BuildRequires: mvn(org.jboss.spec.javax.el:jboss-el-api_2.2_spec)
BuildRequires: mvn(org.jboss.spec.javax.faces:jboss-jsf-api_2.1_spec)
@@ -84,6 +91,7 @@ find -name "*.class" -delete
%patch0 -p0
%patch1 -p1
%patch2 -p0
+%patch3 -p1
sed -i 's/\r//' LICENSE.txt NOTICE.txt
@@ -125,6 +133,9 @@ cd src
%license LICENSE.txt NOTICE.txt
%changelog
+* Mon Mar 30 2015 gil cattaneo <puntogil at libero.it> 1.3.10-14
+- fix CVE-2015-0899 (rhbz#1207099)
+
* Thu Feb 12 2015 gil cattaneo <puntogil at libero.it> 1.3.10-13
- introduce license macro
--
cgit v0.10.2
http://pkgs.fedoraproject.org/cgit/struts.git/commit/?h=master&id=5f83bd9f5d94ea6dd621748a5c637eef2699eb33
More information about the scm-commits
mailing list