diff -Nru tomcat8-8.5.30/debian/changelog tomcat8-8.5.30/debian/changelog --- tomcat8-8.5.30/debian/changelog 2018-04-24 20:47:45.000000000 +0000 +++ tomcat8-8.5.30/debian/changelog 2018-05-31 11:14:54.000000000 +0000 @@ -1,3 +1,15 @@ +tomcat8 (8.5.30-1ubuntu3) cosmic; urgency=medium + + * SECURITY UPDATE: CORS filter has insecure defaults + - debian/patches/CVE-2018-8014.patch: change defaults in + java/org/apache/catalina/filters/CorsFilter.java, + java/org/apache/catalina/filters/LocalStrings.properties, + test/org/apache/catalina/filters/TestCorsFilter.java, + test/org/apache/catalina/filters/TesterFilterConfigs.java. + - CVE-2018-8014 + + -- Marc Deslauriers Thu, 31 May 2018 07:14:54 -0400 + tomcat8 (8.5.30-1ubuntu2) cosmic; urgency=medium * support-jre8.diff: Fix running tomcat with JRE8. (LP: #1765616) diff -Nru tomcat8-8.5.30/debian/control tomcat8-8.5.30/debian/control --- tomcat8-8.5.30/debian/control 2018-04-24 20:47:45.000000000 +0000 +++ tomcat8-8.5.30/debian/control 2018-05-31 11:14:54.000000000 +0000 @@ -1,7 +1,8 @@ Source: tomcat8 Section: java Priority: optional -Maintainer: Debian Java Maintainers +Maintainer: Ubuntu Developers +XSBC-Original-Maintainer: Debian Java Maintainers Uploaders: James Page , tony mancill , diff -Nru tomcat8-8.5.30/debian/patches/CVE-2018-8014.patch tomcat8-8.5.30/debian/patches/CVE-2018-8014.patch --- tomcat8-8.5.30/debian/patches/CVE-2018-8014.patch 1970-01-01 00:00:00.000000000 +0000 +++ tomcat8-8.5.30/debian/patches/CVE-2018-8014.patch 2018-05-31 11:14:52.000000000 +0000 @@ -0,0 +1,262 @@ +Description: fix CORS filter insecure defaults +Origin: backport, https://svn.apache.org/r1831728 +Bug-Debian: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=898935 +Bug: https://bz.apache.org/bugzilla/show_bug.cgi?id=62343 + +Index: tomcat8-8.5.30/java/org/apache/catalina/filters/CorsFilter.java +=================================================================== +--- tomcat8-8.5.30.orig/java/org/apache/catalina/filters/CorsFilter.java 2017-10-04 15:23:02.000000000 -0400 ++++ tomcat8-8.5.30/java/org/apache/catalina/filters/CorsFilter.java 2018-05-30 08:30:25.002938394 -0400 +@@ -267,17 +267,14 @@ public class CorsFilter implements Filte + + // Section 6.1.3 + // Add a single Access-Control-Allow-Origin header. +- if (anyOriginAllowed && !supportsCredentials) { +- // If resource doesn't support credentials and if any origin is +- // allowed +- // to make CORS request, return header with '*'. ++ if (anyOriginAllowed) { ++ // If any origin is allowed, return header with '*'. + response.addHeader( + CorsFilter.RESPONSE_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN, + "*"); + } else { +- // If the resource supports credentials add a single +- // Access-Control-Allow-Origin header, with the value of the Origin +- // header as value. ++ // Add a single Access-Control-Allow-Origin header, with the value ++ // of the Origin header as value. + response.addHeader( + CorsFilter.RESPONSE_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN, + origin); +@@ -781,6 +778,10 @@ public class CorsFilter implements Filte + // For any value other then 'true' this will be false. + this.supportsCredentials = Boolean.parseBoolean(supportsCredentials); + ++ if (this.supportsCredentials && this.anyOriginAllowed) { ++ throw new ServletException(sm.getString("corsFilter.invalidSupportsCredentials")); ++ } ++ + try { + if (!preflightMaxAge.isEmpty()) { + this.preflightMaxAge = Long.parseLong(preflightMaxAge); +@@ -1090,7 +1091,7 @@ public class CorsFilter implements Filte + /** + * By default, all origins are allowed to make requests. + */ +- public static final String DEFAULT_ALLOWED_ORIGINS = "*"; ++ public static final String DEFAULT_ALLOWED_ORIGINS = ""; + + /** + * By default, following methods are supported: GET, POST, HEAD and OPTIONS. +@@ -1106,7 +1107,7 @@ public class CorsFilter implements Filte + /** + * By default, support credentials is turned on. + */ +- public static final String DEFAULT_SUPPORTS_CREDENTIALS = "true"; ++ public static final String DEFAULT_SUPPORTS_CREDENTIALS = "false"; + + /** + * By default, following headers are supported: +Index: tomcat8-8.5.30/java/org/apache/catalina/filters/LocalStrings.properties +=================================================================== +--- tomcat8-8.5.30.orig/java/org/apache/catalina/filters/LocalStrings.properties 2017-04-20 15:13:51.000000000 -0400 ++++ tomcat8-8.5.30/java/org/apache/catalina/filters/LocalStrings.properties 2018-05-30 08:30:25.002938394 -0400 +@@ -14,6 +14,8 @@ + # limitations under the License. + + addDefaultCharset.unsupportedCharset=Specified character set [{0}] is not supported ++ ++corsFilter.invalidSupportsCredentials=It is not allowed to configure supportsCredentials=[true] when allowedOrigins=[*] + corsFilter.invalidPreflightMaxAge=Unable to parse preflightMaxAge + corsFilter.nullRequest=HttpServletRequest object is null + corsFilter.nullRequestType=CORSRequestType object is null +Index: tomcat8-8.5.30/test/org/apache/catalina/filters/TestCorsFilter.java +=================================================================== +--- tomcat8-8.5.30.orig/test/org/apache/catalina/filters/TestCorsFilter.java 2017-01-10 12:09:00.000000000 -0500 ++++ tomcat8-8.5.30/test/org/apache/catalina/filters/TestCorsFilter.java 2018-05-30 08:30:25.002938394 -0400 +@@ -55,8 +55,7 @@ public class TestCorsFilter { + corsFilter.doFilter(request, response, filterChain); + + Assert.assertTrue(response.getHeader( +- CorsFilter.RESPONSE_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN).equals( +- "https://www.apache.org")); ++ CorsFilter.RESPONSE_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN).equals("*")); + Assert.assertTrue(((Boolean) request.getAttribute( + CorsFilter.HTTP_REQUEST_ATTRIBUTE_IS_CORS_REQUEST)).booleanValue()); + Assert.assertTrue(request.getAttribute( +@@ -88,8 +87,7 @@ public class TestCorsFilter { + corsFilter.doFilter(request, response, filterChain); + + Assert.assertTrue(response.getHeader( +- CorsFilter.RESPONSE_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN).equals( +- "https://www.apache.org")); ++ CorsFilter.RESPONSE_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN).equals("*")); + Assert.assertTrue(((Boolean) request.getAttribute( + CorsFilter.HTTP_REQUEST_ATTRIBUTE_IS_CORS_REQUEST)).booleanValue()); + Assert.assertTrue(request.getAttribute( +@@ -120,8 +118,7 @@ public class TestCorsFilter { + corsFilter.doFilter(request, response, filterChain); + + Assert.assertTrue(response.getHeader( +- CorsFilter.RESPONSE_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN).equals( +- "https://www.apache.org")); ++ CorsFilter.RESPONSE_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN).equals("*")); + Assert.assertTrue(((Boolean) request.getAttribute( + CorsFilter.HTTP_REQUEST_ATTRIBUTE_IS_CORS_REQUEST)).booleanValue()); + Assert.assertTrue(request.getAttribute( +@@ -166,41 +163,15 @@ public class TestCorsFilter { + } + + /* +- * Tests the presence of the origin (and not '*') in the response, when +- * supports credentials is enabled alongwith any origin, '*'. ++ * Tests the that supports credentials may not be enabled with any origin, ++ * '*'. + * +- * @throws IOException + * @throws ServletException + */ +- @Test +- public void testDoFilterSimpleAnyOriginAndSupportsCredentials() +- throws IOException, ServletException { +- TesterHttpServletRequest request = new TesterHttpServletRequest(); +- request.setHeader(CorsFilter.REQUEST_HEADER_ORIGIN, +- TesterFilterConfigs.HTTPS_WWW_APACHE_ORG); +- request.setMethod("GET"); +- TesterHttpServletResponse response = new TesterHttpServletResponse(); +- ++ @Test(expected=ServletException.class) ++ public void testDoFilterSimpleAnyOriginAndSupportsCredentials() throws ServletException { + CorsFilter corsFilter = new CorsFilter(); +- corsFilter.init(TesterFilterConfigs +- .getFilterConfigAnyOriginAndSupportsCredentials()); +- corsFilter.doFilter(request, response, filterChain); +- +- Assert.assertTrue(response.getHeader( +- CorsFilter.RESPONSE_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN).equals( +- TesterFilterConfigs.HTTPS_WWW_APACHE_ORG)); +- Assert.assertTrue(response.getHeader( +- CorsFilter.RESPONSE_HEADER_ACCESS_CONTROL_ALLOW_CREDENTIALS) +- .equals( +- "true")); +- Assert.assertTrue(((Boolean) request.getAttribute( +- CorsFilter.HTTP_REQUEST_ATTRIBUTE_IS_CORS_REQUEST)).booleanValue()); +- Assert.assertTrue(request.getAttribute( +- CorsFilter.HTTP_REQUEST_ATTRIBUTE_ORIGIN).equals( +- TesterFilterConfigs.HTTPS_WWW_APACHE_ORG)); +- Assert.assertTrue(request.getAttribute( +- CorsFilter.HTTP_REQUEST_ATTRIBUTE_REQUEST_TYPE).equals( +- CorsFilter.CORSRequestType.SIMPLE.name().toLowerCase(Locale.ENGLISH))); ++ corsFilter.init(TesterFilterConfigs.getFilterConfigAnyOriginAndSupportsCredentials()); + } + + /* +@@ -261,8 +232,7 @@ public class TestCorsFilter { + corsFilter.doFilter(request, response, filterChain); + + Assert.assertTrue(response.getHeader( +- CorsFilter.RESPONSE_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN).equals( +- "https://www.apache.org")); ++ CorsFilter.RESPONSE_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN).equals("*")); + Assert.assertTrue(response.getHeader( + CorsFilter.RESPONSE_HEADER_ACCESS_CONTROL_EXPOSE_HEADERS) + .equals(TesterFilterConfigs.EXPOSED_HEADERS)); +@@ -727,9 +697,8 @@ public class TestCorsFilter { + }); + corsFilter.doFilter(request, response, filterChain); + +- Assert.assertTrue(response.getHeader( +- CorsFilter.RESPONSE_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN).equals( +- "https://www.apache.org")); ++ Assert.assertNull(response.getHeader( ++ CorsFilter.RESPONSE_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN)); + Assert.assertTrue(((Boolean) request.getAttribute( + CorsFilter.HTTP_REQUEST_ATTRIBUTE_IS_CORS_REQUEST)).booleanValue()); + Assert.assertTrue(request.getAttribute( +@@ -1412,7 +1381,7 @@ public class TestCorsFilter { + Assert.assertTrue(corsFilter.getAllowedOrigins().size() == 0); + Assert.assertTrue(corsFilter.isAnyOriginAllowed()); + Assert.assertTrue(corsFilter.getExposedHeaders().size() == 0); +- Assert.assertTrue(corsFilter.isSupportsCredentials()); ++ Assert.assertFalse(corsFilter.isSupportsCredentials()); + Assert.assertTrue(corsFilter.getPreflightMaxAge() == 1800); + } + +@@ -1448,9 +1417,9 @@ public class TestCorsFilter { + Assert.assertTrue(corsFilter.getAllowedHttpHeaders().size() == 6); + Assert.assertTrue(corsFilter.getAllowedHttpMethods().size() == 4); + Assert.assertTrue(corsFilter.getAllowedOrigins().size() == 0); +- Assert.assertTrue(corsFilter.isAnyOriginAllowed()); ++ Assert.assertFalse(corsFilter.isAnyOriginAllowed()); + Assert.assertTrue(corsFilter.getExposedHeaders().size() == 0); +- Assert.assertTrue(corsFilter.isSupportsCredentials()); ++ Assert.assertFalse(corsFilter.isSupportsCredentials()); + Assert.assertTrue(corsFilter.getPreflightMaxAge() == 1800); + } + +@@ -1554,8 +1523,7 @@ public class TestCorsFilter { + corsFilter.doFilter(request, response, filterChain); + + Assert.assertTrue(response.getHeader( +- CorsFilter.RESPONSE_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN).equals( +- "https://www.apache.org")); ++ CorsFilter.RESPONSE_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN).equals("*")); + Assert.assertNull(request + .getAttribute(CorsFilter.HTTP_REQUEST_ATTRIBUTE_IS_CORS_REQUEST)); + Assert.assertNull(request +Index: tomcat8-8.5.30/test/org/apache/catalina/filters/TesterFilterConfigs.java +=================================================================== +--- tomcat8-8.5.30.orig/test/org/apache/catalina/filters/TesterFilterConfigs.java 2015-11-30 05:54:14.000000000 -0500 ++++ tomcat8-8.5.30/test/org/apache/catalina/filters/TesterFilterConfigs.java 2018-05-30 08:30:25.002938394 -0400 +@@ -36,12 +36,13 @@ public class TesterFilterConfigs { + public static final TesterServletContext mockServletContext = + new TesterServletContext(); + ++ // Default config for the test is to allow any origin + public static FilterConfig getDefaultFilterConfig() { + final String allowedHttpHeaders = + CorsFilter.DEFAULT_ALLOWED_HTTP_HEADERS; + final String allowedHttpMethods = + CorsFilter.DEFAULT_ALLOWED_HTTP_METHODS; +- final String allowedOrigins = CorsFilter.DEFAULT_ALLOWED_ORIGINS; ++ final String allowedOrigins = ANY_ORIGIN; + final String exposedHeaders = CorsFilter.DEFAULT_EXPOSED_HEADERS; + final String supportCredentials = + CorsFilter.DEFAULT_SUPPORTS_CREDENTIALS; +@@ -59,7 +60,7 @@ public class TesterFilterConfigs { + CorsFilter.DEFAULT_ALLOWED_HTTP_HEADERS; + final String allowedHttpMethods = + CorsFilter.DEFAULT_ALLOWED_HTTP_METHODS + ",PUT"; +- final String allowedOrigins = CorsFilter.DEFAULT_ALLOWED_ORIGINS; ++ final String allowedOrigins = ANY_ORIGIN; + final String exposedHeaders = CorsFilter.DEFAULT_EXPOSED_HEADERS; + final String supportCredentials = "true"; + final String preflightMaxAge = +@@ -77,7 +78,7 @@ public class TesterFilterConfigs { + CorsFilter.DEFAULT_ALLOWED_HTTP_HEADERS; + final String allowedHttpMethods = + CorsFilter.DEFAULT_ALLOWED_HTTP_METHODS + ",PUT"; +- final String allowedOrigins = CorsFilter.DEFAULT_ALLOWED_ORIGINS; ++ final String allowedOrigins = ANY_ORIGIN; + final String exposedHeaders = CorsFilter.DEFAULT_EXPOSED_HEADERS; + final String supportCredentials = "false"; + final String preflightMaxAge = +@@ -131,7 +132,7 @@ public class TesterFilterConfigs { + CorsFilter.DEFAULT_ALLOWED_HTTP_HEADERS; + final String allowedHttpMethods = + CorsFilter.DEFAULT_ALLOWED_HTTP_METHODS; +- final String allowedOrigins = CorsFilter.DEFAULT_ALLOWED_ORIGINS; ++ final String allowedOrigins = ANY_ORIGIN; + final String exposedHeaders = EXPOSED_HEADERS; + final String supportCredentials = + CorsFilter.DEFAULT_SUPPORTS_CREDENTIALS; +@@ -240,7 +241,7 @@ public class TesterFilterConfigs { + CorsFilter.DEFAULT_ALLOWED_HTTP_HEADERS; + final String allowedHttpMethods = + CorsFilter.DEFAULT_ALLOWED_HTTP_METHODS; +- final String allowedOrigins = CorsFilter.DEFAULT_ALLOWED_ORIGINS; ++ final String allowedOrigins = ANY_ORIGIN; + final String exposedHeaders = CorsFilter.DEFAULT_EXPOSED_HEADERS; + final String supportCredentials = + CorsFilter.DEFAULT_SUPPORTS_CREDENTIALS; diff -Nru tomcat8-8.5.30/debian/patches/series tomcat8-8.5.30/debian/patches/series --- tomcat8-8.5.30/debian/patches/series 2018-04-24 20:47:45.000000000 +0000 +++ tomcat8-8.5.30/debian/patches/series 2018-05-31 11:14:52.000000000 +0000 @@ -9,3 +9,4 @@ 0019-add-distribution-to-error-page.patch 0021-dont-test-unsupported-ciphers.patch support-jre8.diff +CVE-2018-8014.patch