CVE-2016-6812
Description
The HTTP transport module in Apache CXF prior to 3.0.12 and 3.1.x prior to 3.1.9 uses FormattedServiceListWriter to provide an HTML page which lists the names and absolute URL addresses of the available service endpoints. The module calculates the base URL using the current HttpServletRequest. The calculated base URL is used by FormattedServiceListWriter to build the service endpoint absolute URLs. If the unexpected matrix parameters have been injected into the request URL then these matrix parameters will find their way back to the client in the services list page which represents an XSS risk to the client.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
org.apache.cxf:cxf-coreMaven | < 3.0.12 | 3.0.12 |
org.apache.cxf:cxf-coreMaven | >= 3.1.0, < 3.1.9 | 3.1.9 |
Affected products
2- Apache Software Foundation/Apache CXFv5Range: prior to 3.0.12
Patches
41f824d8039c7[CXF-6216] Better stripping of matrix params
5 files changed · +44 −18
distribution/src/main/release/samples/jax_rs/spring_boot/src/main/java/sample/rs/service/SampleRestApplication.java+1 −1 modified@@ -45,7 +45,7 @@ public Server rsServer() { JAXRSServerFactoryBean endpoint = new JAXRSServerFactoryBean(); endpoint.setBus(bus); endpoint.setServiceBeans(Arrays.<Object>asList(new HelloServiceImpl1(), new HelloServiceImpl2())); - endpoint.setAddress("/"); + endpoint.setAddress("/a"); endpoint.setFeatures(Arrays.asList(new Swagger2Feature())); return endpoint.create(); }
rt/transports/http/src/main/java/org/apache/cxf/transport/servlet/BaseUrlHelper.java+8 −12 modified@@ -36,9 +36,8 @@ private BaseUrlHelper() { */ public static String getBaseURL(HttpServletRequest request) { String reqPrefix = request.getRequestURL().toString(); - String pathInfo = request.getPathInfo() == null ? "" : request.getPathInfo(); - //fix for CXF-898 - if (!"/".equals(pathInfo) || reqPrefix.endsWith("/")) { + String pathInfo = request.getPathInfo(); + if (!"/".equals(pathInfo) || reqPrefix.contains(";")) { StringBuilder sb = new StringBuilder(); // request.getScheme(), request.getLocalName() and request.getLocalPort() // should be marginally cheaper - provided request.getLocalName() does @@ -47,19 +46,16 @@ public static String getBaseURL(HttpServletRequest request) { URI uri = URI.create(reqPrefix); sb.append(uri.getScheme()).append("://").append(uri.getRawAuthority()); - if (request.getContextPath() != null) { - sb.append(request.getContextPath()); + String contextPath = request.getContextPath(); + if (contextPath != null) { + sb.append(contextPath); } - if (request.getServletPath() != null) { - sb.append(request.getServletPath()); + String servletPath = request.getServletPath(); + if (servletPath != null) { + sb.append(servletPath); } reqPrefix = sb.toString(); - } else { - int matrixParamIndex = reqPrefix.indexOf(";"); - if (matrixParamIndex > 0) { - reqPrefix = reqPrefix.substring(0, matrixParamIndex); - } } return reqPrefix; }
rt/transports/http/src/main/java/org/apache/cxf/transport/servlet/servicelist/ServiceListGeneratorServlet.java+13 −5 modified@@ -103,12 +103,20 @@ public void service(HttpServletRequest request, if (serviceListStyleSheet != null) { styleSheetPath = request.getContextPath() + "/" + serviceListStyleSheet; } else { - String requestUri = request.getRequestURI(); - int matrixParamIndex = requestUri.indexOf(";"); - if (matrixParamIndex > 0) { - requestUri = requestUri.substring(0, matrixParamIndex); + styleSheetPath = ""; + String contextPath = request.getContextPath(); + if (contextPath != null) { + styleSheetPath += contextPath; } - styleSheetPath = requestUri; + String servletPath = request.getServletPath(); + if (servletPath != null) { + styleSheetPath += servletPath; + } + String pathInfo = request.getPathInfo(); + if (pathInfo != null) { + styleSheetPath += pathInfo; + } + if (!styleSheetPath.endsWith("/")) { styleSheetPath += "/"; }
systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerSpringBookTest.java+10 −0 modified@@ -133,6 +133,16 @@ public void testGetServicesPageWithServletPatternMatchOnly() throws Exception { assertFalse(s.contains(";a=b")); assertTrue(s.contains("<a href=\"http://localhost:" + PORT + "/the/")); } + @Test + public void testGetServicesPageWithServletPatternMatchOnly2() throws Exception { + final String address = "http://localhost:" + PORT + "/services;a=b;/list;a=b/;a=b"; + WebClient wc = WebClient.create(address).accept("text/*"); + String s = wc.get(String.class); + assertTrue(s.contains("href=\"/services/list/?stylesheet=1\"")); + assertTrue(s.contains("<title>CXF - Service list</title>")); + assertFalse(s.contains(";a=b")); + assertTrue(s.contains("<a href=\"http://localhost:" + PORT + "/services/list/")); + } @Test public void testEchoBookForm() throws Exception {
systests/jaxrs/src/test/resources/jaxrs/WEB-INF/web.xml+12 −0 modified@@ -51,6 +51,14 @@ </init-param> <load-on-startup>1</load-on-startup> </servlet> + <servlet> + <servlet-name>CXFServlet3</servlet-name> + <display-name>CXF Servlet3</display-name> + <servlet-class> + org.apache.cxf.transport.servlet.CXFServlet + </servlet-class> + <load-on-startup>1</load-on-startup> + </servlet> <servlet-mapping> <servlet-name>CXFServlet</servlet-name> <url-pattern>/the/*</url-pattern> @@ -59,5 +67,9 @@ <servlet-name>CXFServlet2</servlet-name> <url-pattern>/bus/*</url-pattern> </servlet-mapping> + <servlet-mapping> + <servlet-name>CXFServlet3</servlet-name> + <url-pattern>/services/list/*</url-pattern> + </servlet-mapping> </web-app> <!-- END SNIPPET: webxml -->
a30397b0Better stripping of matrix parameters
4 files changed · +43 −17
rt/transports/http/src/main/java/org/apache/cxf/transport/servlet/BaseUrlHelper.java+8 −12 modified@@ -36,9 +36,8 @@ private BaseUrlHelper() { */ public static String getBaseURL(HttpServletRequest request) { String reqPrefix = request.getRequestURL().toString(); - String pathInfo = request.getPathInfo() == null ? "" : request.getPathInfo(); - //fix for CXF-898 - if (!"/".equals(pathInfo) || reqPrefix.endsWith("/")) { + String pathInfo = request.getPathInfo(); + if (!"/".equals(pathInfo) || reqPrefix.contains(";")) { StringBuilder sb = new StringBuilder(); // request.getScheme(), request.getLocalName() and request.getLocalPort() // should be marginally cheaper - provided request.getLocalName() does @@ -47,19 +46,16 @@ public static String getBaseURL(HttpServletRequest request) { URI uri = URI.create(reqPrefix); sb.append(uri.getScheme()).append("://").append(uri.getRawAuthority()); - if (request.getContextPath() != null) { - sb.append(request.getContextPath()); + String contextPath = request.getContextPath(); + if (contextPath != null) { + sb.append(contextPath); } - if (request.getServletPath() != null) { - sb.append(request.getServletPath()); + String servletPath = request.getServletPath(); + if (servletPath != null) { + sb.append(servletPath); } reqPrefix = sb.toString(); - } else { - int matrixParamIndex = reqPrefix.indexOf(";"); - if (matrixParamIndex > 0) { - reqPrefix = reqPrefix.substring(0, matrixParamIndex); - } } return reqPrefix; }
rt/transports/http/src/main/java/org/apache/cxf/transport/servlet/servicelist/ServiceListGeneratorServlet.java+13 −5 modified@@ -112,12 +112,20 @@ public void service(HttpServletRequest request, if (serviceListStyleSheet != null) { styleSheetPath = request.getContextPath() + "/" + serviceListStyleSheet; } else { - String requestUri = request.getRequestURI(); - int matrixParamIndex = requestUri.indexOf(";"); - if (matrixParamIndex > 0) { - requestUri = requestUri.substring(0, matrixParamIndex); + styleSheetPath = ""; + String contextPath = request.getContextPath(); + if (contextPath != null) { + styleSheetPath += contextPath; } - styleSheetPath = requestUri; + String servletPath = request.getServletPath(); + if (servletPath != null) { + styleSheetPath += servletPath; + } + String pathInfo = request.getPathInfo(); + if (pathInfo != null) { + styleSheetPath += pathInfo; + } + if (!styleSheetPath.endsWith("/")) { styleSheetPath += "/"; }
systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerSpringBookTest.java+10 −0 modified@@ -133,6 +133,16 @@ public void testGetServicesPageWithServletPatternMatchOnly() throws Exception { assertFalse(s.contains(";a=b")); assertTrue(s.contains("<a href=\"http://localhost:" + PORT + "/the/")); } + @Test + public void testGetServicesPageWithServletPatternMatchOnly2() throws Exception { + final String address = "http://localhost:" + PORT + "/services;a=b;/list;a=b/;a=b"; + WebClient wc = WebClient.create(address).accept("text/*"); + String s = wc.get(String.class); + assertTrue(s.contains("href=\"/services/list/?stylesheet=1\"")); + assertTrue(s.contains("<title>CXF - Service list</title>")); + assertFalse(s.contains(";a=b")); + assertTrue(s.contains("<a href=\"http://localhost:" + PORT + "/services/list/")); + } @Test public void testEchoBookForm() throws Exception {
systests/jaxrs/src/test/resources/jaxrs/WEB-INF/web.xml+12 −0 modified@@ -51,6 +51,14 @@ </init-param> <load-on-startup>1</load-on-startup> </servlet> + <servlet> + <servlet-name>CXFServlet3</servlet-name> + <display-name>CXF Servlet3</display-name> + <servlet-class> + org.apache.cxf.transport.servlet.CXFServlet + </servlet-class> + <load-on-startup>1</load-on-startup> + </servlet> <servlet-mapping> <servlet-name>CXFServlet</servlet-name> <url-pattern>/the/*</url-pattern> @@ -59,5 +67,9 @@ <servlet-name>CXFServlet2</servlet-name> <url-pattern>/bus/*</url-pattern> </servlet-mapping> + <servlet-mapping> + <servlet-name>CXFServlet3</servlet-name> + <url-pattern>/services/list/*</url-pattern> + </servlet-mapping> </web-app> <!-- END SNIPPET: webxml -->
32e89366e2da[CXF-6216] Stripping away the matrix parameters if any from the base URL
4 files changed · +48 −4
rt/transports/http/src/main/java/org/apache/cxf/transport/servlet/BaseUrlHelper.java+5 −0 modified@@ -55,6 +55,11 @@ public static String getBaseURL(HttpServletRequest request) { } reqPrefix = sb.toString(); + } else { + int matrixParamIndex = reqPrefix.indexOf(";"); + if (matrixParamIndex > 0) { + reqPrefix = reqPrefix.substring(0, matrixParamIndex); + } } return reqPrefix; }
rt/transports/http/src/main/java/org/apache/cxf/transport/servlet/servicelist/FormattedServiceListWriter.java+5 −1 modified@@ -146,7 +146,11 @@ private String getAbsoluteAddress(String basePath, AbstractDestination d) { return null; } } else { - return basePath + endpointAddress; + String address = basePath; + if (address.endsWith("/") && endpointAddress.startsWith("/")) { + address = address.substring(0, address.length() - 1); + } + return address + endpointAddress; } }
rt/transports/http/src/main/java/org/apache/cxf/transport/servlet/servicelist/ServiceListGeneratorServlet.java+10 −2 modified@@ -102,9 +102,17 @@ public void service(HttpServletRequest request, String styleSheetPath; if (serviceListStyleSheet != null) { styleSheetPath = request.getContextPath() + "/" + serviceListStyleSheet; - } else { - styleSheetPath = request.getRequestURI() + "/?stylesheet=1"; + String requestUri = request.getRequestURI(); + int matrixParamIndex = requestUri.indexOf(";"); + if (matrixParamIndex > 0) { + requestUri = requestUri.substring(0, matrixParamIndex); + } + styleSheetPath = requestUri; + if (!styleSheetPath.endsWith("/")) { + styleSheetPath += "/"; + } + styleSheetPath += "?stylesheet=1"; } serviceListWriter = new FormattedServiceListWriter(styleSheetPath, title, showForeignContexts, bus);
systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerSpringBookTest.java+28 −1 modified@@ -85,7 +85,6 @@ public static void startServers() throws Exception { public void testGetGenericBook() throws Exception { String baseAddress = "http://localhost:" + PORT + "/the/thebooks8/books"; WebClient wc = WebClient.create(baseAddress); - WebClient.getConfig(wc).getHttpConduit().getClient().setReceiveTimeout(10000000); Long id = wc.type("application/xml").accept("text/plain").post(new Book("CXF", 1L), Long.class); assertEquals(new Long(1), id); Book book = wc.replaceHeader("Accept", "application/xml").query("id", 1L).get(Book.class); @@ -103,10 +102,38 @@ public void testGetBookWebEx() throws Exception { public void testGetBookText() throws Exception { final String address = "http://localhost:" + PORT + "/the/thebooks/bookstore/books/text"; WebClient wc = WebClient.create(address).accept("text/*"); + WebClient.getConfig(wc).getHttpConduit().getClient().setReceiveTimeout(10000000); assertEquals(406, wc.get().getStatus()); } + @Test + public void testGetServicesPageNotFound() throws Exception { + final String address = "http://localhost:" + PORT + "/the/services;a=b"; + WebClient wc = WebClient.create(address).accept("text/*"); + WebClient.getConfig(wc).getHttpConduit().getClient().setReceiveTimeout(10000000); + assertEquals(404, wc.get().getStatus()); + } + @Test + public void testGetServicesPage() throws Exception { + final String address = "http://localhost:" + PORT + "/the/services"; + WebClient wc = WebClient.create(address).accept("text/*"); + String s = wc.get(String.class); + assertTrue(s.contains("href=\"/the/services/?stylesheet=1\"")); + assertTrue(s.contains("<title>CXF - Service list</title>")); + assertTrue(s.contains("<a href=\"http://localhost:" + PORT + "/the/")); + } + @Test + public void testGetServicesPageWithServletPatternMatchOnly() throws Exception { + final String address = "http://localhost:" + PORT + "/the/;a=b"; + WebClient wc = WebClient.create(address).accept("text/*"); + String s = wc.get(String.class); + assertTrue(s.contains("href=\"/the/?stylesheet=1\"")); + assertTrue(s.contains("<title>CXF - Service list</title>")); + assertFalse(s.contains(";a=b")); + assertTrue(s.contains("<a href=\"http://localhost:" + PORT + "/the/")); + } + @Test public void testEchoBookForm() throws Exception { String address = "http://localhost:" + PORT + "/bus/thebooksform/bookform";
1be97cb13aef[CXF-6216] Stripping away the matrix parameters if any from the base URL
4 files changed · +48 −4
rt/transports/http/src/main/java/org/apache/cxf/transport/servlet/BaseUrlHelper.java+5 −0 modified@@ -55,6 +55,11 @@ public static String getBaseURL(HttpServletRequest request) { } reqPrefix = sb.toString(); + } else { + int matrixParamIndex = reqPrefix.indexOf(";"); + if (matrixParamIndex > 0) { + reqPrefix = reqPrefix.substring(0, matrixParamIndex); + } } return reqPrefix; }
rt/transports/http/src/main/java/org/apache/cxf/transport/servlet/servicelist/FormattedServiceListWriter.java+5 −1 modified@@ -133,7 +133,11 @@ private String getAbsoluteAddress(String basePath, AbstractDestination d) { return null; } } else { - return basePath + endpointAddress; + String address = basePath; + if (address.endsWith("/") && endpointAddress.startsWith("/")) { + address = address.substring(0, address.length() - 1); + } + return address + endpointAddress; } }
rt/transports/http/src/main/java/org/apache/cxf/transport/servlet/servicelist/ServiceListGeneratorServlet.java+10 −2 modified@@ -111,9 +111,17 @@ public void service(HttpServletRequest request, String styleSheetPath; if (serviceListStyleSheet != null) { styleSheetPath = request.getContextPath() + "/" + serviceListStyleSheet; - } else { - styleSheetPath = request.getRequestURI() + "/?stylesheet=1"; + String requestUri = request.getRequestURI(); + int matrixParamIndex = requestUri.indexOf(";"); + if (matrixParamIndex > 0) { + requestUri = requestUri.substring(0, matrixParamIndex); + } + styleSheetPath = requestUri; + if (!styleSheetPath.endsWith("/")) { + styleSheetPath += "/"; + } + styleSheetPath += "?stylesheet=1"; } serviceListWriter = new FormattedServiceListWriter(styleSheetPath, title, showForeignContexts, atomMap);
systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerSpringBookTest.java+28 −1 modified@@ -85,7 +85,6 @@ public static void startServers() throws Exception { public void testGetGenericBook() throws Exception { String baseAddress = "http://localhost:" + PORT + "/the/thebooks8/books"; WebClient wc = WebClient.create(baseAddress); - WebClient.getConfig(wc).getHttpConduit().getClient().setReceiveTimeout(10000000); Long id = wc.type("application/xml").accept("text/plain").post(new Book("CXF", 1L), Long.class); assertEquals(new Long(1), id); Book book = wc.replaceHeader("Accept", "application/xml").query("id", 1L).get(Book.class); @@ -103,10 +102,38 @@ public void testGetBookWebEx() throws Exception { public void testGetBookText() throws Exception { final String address = "http://localhost:" + PORT + "/the/thebooks/bookstore/books/text"; WebClient wc = WebClient.create(address).accept("text/*"); + WebClient.getConfig(wc).getHttpConduit().getClient().setReceiveTimeout(10000000); assertEquals(406, wc.get().getStatus()); } + @Test + public void testGetServicesPageNotFound() throws Exception { + final String address = "http://localhost:" + PORT + "/the/services;a=b"; + WebClient wc = WebClient.create(address).accept("text/*"); + WebClient.getConfig(wc).getHttpConduit().getClient().setReceiveTimeout(10000000); + assertEquals(404, wc.get().getStatus()); + } + @Test + public void testGetServicesPage() throws Exception { + final String address = "http://localhost:" + PORT + "/the/services"; + WebClient wc = WebClient.create(address).accept("text/*"); + String s = wc.get(String.class); + assertTrue(s.contains("href=\"/the/services/?stylesheet=1\"")); + assertTrue(s.contains("<title>CXF - Service list</title>")); + assertTrue(s.contains("<a href=\"http://localhost:" + PORT + "/the/")); + } + @Test + public void testGetServicesPageWithServletPatternMatchOnly() throws Exception { + final String address = "http://localhost:" + PORT + "/the/;a=b"; + WebClient wc = WebClient.create(address).accept("text/*"); + String s = wc.get(String.class); + assertTrue(s.contains("href=\"/the/?stylesheet=1\"")); + assertTrue(s.contains("<title>CXF - Service list</title>")); + assertFalse(s.contains(";a=b")); + assertTrue(s.contains("<a href=\"http://localhost:" + PORT + "/the/")); + } + @Test public void testEchoBookForm() throws Exception { String address = "http://localhost:" + PORT + "/bus/thebooksform/bookform";
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
23- cxf.apache.org/security-advisories.data/CVE-2016-6812.txt.ascnvdPatchVendor AdvisoryWEB
- www.securityfocus.com/bid/97582nvdThird Party AdvisoryVDB Entry
- www.securitytracker.com/id/1037543nvdThird Party AdvisoryVDB Entry
- github.com/advisories/GHSA-vw2c-5wph-v92rghsaADVISORY
- issues.apache.org/jira/browse/CXF-6216nvdIssue TrackingVendor AdvisoryWEB
- nvd.nist.gov/vuln/detail/CVE-2016-6812ghsaADVISORY
- access.redhat.com/errata/RHSA-2017:0868nvdWEB
- github.com/apache/cxf/commit/1be97cb13aef121b799b1be4d9793c0e8b925a12ghsaWEB
- github.com/apache/cxf/commit/1f824d8039c7a42a4aa46f844e6c800e1143c7e7ghsaWEB
- github.com/apache/cxf/commit/32e89366e2daa5670ac7a5c5c19f0bf9329a4c1eghsaWEB
- github.com/apache/cxf/commit/a30397b0ghsaWEB
- lists.apache.org/thread.html/r36e44ffc1a9b365327df62cdfaabe85b9a5637de102cea07d79b2dbf@%3Ccommits.cxf.apache.org%3EghsaWEB
- lists.apache.org/thread.html/rc774278135816e7afc943dc9fc78eb0764f2c84a2b96470a0187315c@%3Ccommits.cxf.apache.org%3EghsaWEB
- lists.apache.org/thread.html/rd49aabd984ed540c8ff7916d4d79405f3fa311d2fdbcf9ed307839a6@%3Ccommits.cxf.apache.org%3EghsaWEB
- lists.apache.org/thread.html/rec7160382badd3ef4ad017a22f64a266c7188b9ba71394f0d321e2d4@%3Ccommits.cxf.apache.org%3EghsaWEB
- lists.apache.org/thread.html/rfb87e0bf3995e7d560afeed750fac9329ff5f1ad49da365129b7f89e@%3Ccommits.cxf.apache.org%3EghsaWEB
- lists.apache.org/thread.html/rff42cfa5e7d75b7c1af0e37589140a8f1999e578a75738740b244bd4@%3Ccommits.cxf.apache.org%3EghsaWEB
- lists.apache.org/thread.html/r36e44ffc1a9b365327df62cdfaabe85b9a5637de102cea07d79b2dbf%40%3Ccommits.cxf.apache.org%3Envd
- lists.apache.org/thread.html/rc774278135816e7afc943dc9fc78eb0764f2c84a2b96470a0187315c%40%3Ccommits.cxf.apache.org%3Envd
- lists.apache.org/thread.html/rd49aabd984ed540c8ff7916d4d79405f3fa311d2fdbcf9ed307839a6%40%3Ccommits.cxf.apache.org%3Envd
- lists.apache.org/thread.html/rec7160382badd3ef4ad017a22f64a266c7188b9ba71394f0d321e2d4%40%3Ccommits.cxf.apache.org%3Envd
- lists.apache.org/thread.html/rfb87e0bf3995e7d560afeed750fac9329ff5f1ad49da365129b7f89e%40%3Ccommits.cxf.apache.org%3Envd
- lists.apache.org/thread.html/rff42cfa5e7d75b7c1af0e37589140a8f1999e578a75738740b244bd4%40%3Ccommits.cxf.apache.org%3Envd
News mentions
0No linked articles in our index yet.