From 974909734cfc18f4550679d7183ec7a0d5081a29 Mon Sep 17 00:00:00 2001 From: mayp Date: Tue, 11 Apr 2023 16:05:25 +0800 Subject: [PATCH 1/6] fix CVE-2023-28708 --- CVE-2023-28708.patch | 235 +++++++++++++++++++++++++++++++++++++++++++ tomcat.spec | 6 +- 2 files changed, 240 insertions(+), 1 deletion(-) create mode 100644 CVE-2023-28708.patch diff --git a/CVE-2023-28708.patch b/CVE-2023-28708.patch new file mode 100644 index 0000000..3d745e8 --- /dev/null +++ b/CVE-2023-28708.patch @@ -0,0 +1,235 @@ +From ca62c90b9e02a9931a2ce5acc61806858591d8b1 Mon Sep 17 00:00:00 2001 +From: mayp +Date: Tue, 11 Apr 2023 15:52:50 +0800 +Subject: [PATCH] Please enter the commit message for your changes. Lines + starting with '' will be ignored, and an empty message aborts the commit. + + On branch master + Changes to be committed: + modified: java/org/apache/catalina/Globals.java + modified: java/org/apache/catalina/connector/Request.java + modified: java/org/apache/catalina/filters/RemoteIpFilter.java + modified: test/org/apache/catalina/filters/TestRemoteIpFilter.java + modified: webapps/docs/changelog.xml +--- + java/org/apache/catalina/Globals.java | 7 ++ + .../apache/catalina/connector/Request.java | 14 +++ + .../catalina/filters/RemoteIpFilter.java | 7 +- + .../catalina/filters/TestRemoteIpFilter.java | 96 ++++++++++++++----- + webapps/docs/changelog.xml | 5 + + 5 files changed, 100 insertions(+), 29 deletions(-) + +diff --git a/java/org/apache/catalina/Globals.java b/java/org/apache/catalina/Globals.java +index 994902b..5b4cad6 100644 +--- a/java/org/apache/catalina/Globals.java ++++ b/java/org/apache/catalina/Globals.java +@@ -144,6 +144,13 @@ public final class Globals { + org.apache.coyote.Constants.SENDFILE_SUPPORTED_ATTR; + + ++ /** ++ * The request attribute that is set to the value of {@code Boolean.TRUE} ++ * if {@link org.apache.catalina.filters.RemoteIpFilter} determines ++ * that this request was submitted via a secure channel. ++ */ ++ public static final String REMOTE_IP_FILTER_SECURE = "org.apache.catalina.filters.RemoteIpFilter.secure"; ++ + /** + * The request attribute that can be used by a servlet to pass + * to the connector the name of the file that is to be served +diff --git a/java/org/apache/catalina/connector/Request.java b/java/org/apache/catalina/connector/Request.java +index c4cc26a..dd4c881 100644 +--- a/java/org/apache/catalina/connector/Request.java ++++ b/java/org/apache/catalina/connector/Request.java +@@ -3487,6 +3487,20 @@ public class Request implements HttpServletRequest { + // NO-OP + } + }); ++ specialAttributes.put(Globals.REMOTE_IP_FILTER_SECURE, ++ new SpecialAttributeAdapter() { ++ @Override ++ public Object get(Request request, String name) { ++ return Boolean.valueOf(request.isSecure()); ++ } ++ ++ @Override ++ public void set(Request request, String name, Object value) { ++ if (value instanceof Boolean) { ++ request.setSecure(((Boolean) value).booleanValue()); ++ } ++ } ++ }); + + for (SimpleDateFormat sdf : formatsTemplate) { + sdf.setTimeZone(GMT_ZONE); +diff --git a/java/org/apache/catalina/filters/RemoteIpFilter.java b/java/org/apache/catalina/filters/RemoteIpFilter.java +index b9f6655..e978cfb 100644 +--- a/java/org/apache/catalina/filters/RemoteIpFilter.java ++++ b/java/org/apache/catalina/filters/RemoteIpFilter.java +@@ -577,11 +577,6 @@ public class RemoteIpFilter extends GenericFilter { + return serverPort; + } + +- @Override +- public boolean isSecure() { +- return secure; +- } +- + public void removeHeader(String name) { + Map.Entry> header = getHeaderEntry(name); + if (header != null) { +@@ -617,7 +612,7 @@ public class RemoteIpFilter extends GenericFilter { + } + + public void setSecure(boolean secure) { +- this.secure = secure; ++ super.getRequest().setAttribute(Globals.REMOTE_IP_FILTER_SECURE, Boolean.valueOf(secure)); + } + + public void setServerPort(int serverPort) { +diff --git a/test/org/apache/catalina/filters/TestRemoteIpFilter.java b/test/org/apache/catalina/filters/TestRemoteIpFilter.java +index f7f2093..109fdd2 100644 +--- a/test/org/apache/catalina/filters/TestRemoteIpFilter.java ++++ b/test/org/apache/catalina/filters/TestRemoteIpFilter.java +@@ -81,15 +81,21 @@ public class TestRemoteIpFilter extends TomcatBaseTest { + + private static final long serialVersionUID = 1L; + +- private transient HttpServletRequest request; +- +- public HttpServletRequest getRequest() { +- return request; +- } ++ public String remoteAddr; ++ public String remoteHost; ++ public String scheme; ++ public String serverName; ++ public int serverPort; ++ public boolean isSecure; + + @Override + public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { +- this.request = request; ++ this.isSecure = request.isSecure(); ++ this.remoteAddr = request.getRemoteAddr(); ++ this.remoteHost = request.getRemoteHost(); ++ this.scheme = request.getScheme(); ++ this.serverName = request.getServerName(); ++ this.serverPort = request.getServerPort(); + PrintWriter writer = response.getWriter(); + + writer.println("request.remoteAddr=" + request.getRemoteAddr()); +@@ -127,16 +133,6 @@ public class TestRemoteIpFilter extends TomcatBaseTest { + getCoyoteRequest().scheme().setString(scheme); + } + +- @Override +- public void setAttribute(String name, Object value) { +- getCoyoteRequest().getAttributes().put(name, value); +- } +- +- @Override +- public Object getAttribute(String name) { +- return getCoyoteRequest().getAttributes().get(name); +- } +- + @Override + public String getServerName() { + return "localhost"; +@@ -667,16 +663,70 @@ public class TestRemoteIpFilter extends TomcatBaseTest { + + // VALIDATE + Assert.assertEquals(HttpURLConnection.HTTP_OK, httpURLConnection.getResponseCode()); +- HttpServletRequest request = mockServlet.getRequest(); +- Assert.assertNotNull(request); + + // VALIDATE X-FORWARDED-FOR +- Assert.assertEquals(expectedRemoteAddr, request.getRemoteAddr()); +- Assert.assertEquals(expectedRemoteAddr, request.getRemoteHost()); ++ Assert.assertEquals(expectedRemoteAddr, mockServlet.remoteAddr); ++ Assert.assertEquals(expectedRemoteAddr, mockServlet.remoteHost); + + // VALIDATE X-FORWARDED-PROTO +- Assert.assertTrue(request.isSecure()); +- Assert.assertEquals("https", request.getScheme()); +- Assert.assertEquals(443, request.getServerPort()); ++ Assert.assertTrue(mockServlet.isSecure); ++ Assert.assertEquals("https", mockServlet.scheme); ++ Assert.assertEquals(443, mockServlet.serverPort); ++ } ++ ++ @Test ++ public void testJSessionIdSecureAttributeMissing() throws Exception { ++ ++ // mostly default configuration : enable "x-forwarded-proto" ++ Map remoteIpFilterParameter = new HashMap<>(); ++ remoteIpFilterParameter.put("protocolHeader", "x-forwarded-proto"); ++ ++ // SETUP ++ Tomcat tomcat = getTomcatInstance(); ++ Context root = tomcat.addContext("", TEMP_DIR); ++ ++ FilterDef filterDef = new FilterDef(); ++ filterDef.getParameterMap().putAll(remoteIpFilterParameter); ++ filterDef.setFilterClass(RemoteIpFilter.class.getName()); ++ filterDef.setFilterName(RemoteIpFilter.class.getName()); ++ ++ root.addFilterDef(filterDef); ++ ++ FilterMap filterMap = new FilterMap(); ++ filterMap.setFilterName(RemoteIpFilter.class.getName()); ++ filterMap.addURLPatternDecoded("*"); ++ root.addFilterMap(filterMap); ++ ++ Bug66471Servlet bug66471Servlet = new Bug66471Servlet(); ++ ++ Tomcat.addServlet(root, bug66471Servlet.getClass().getName(), bug66471Servlet); ++ root.addServletMappingDecoded("/test", bug66471Servlet.getClass().getName()); ++ ++ getTomcatInstance().start(); ++ ++ Map> resHeaders = new HashMap<>(); ++ Map> reqHeaders = new HashMap<>(); ++ String expectedRemoteAddr = "my-remote-addr"; ++ List forwardedFor = new ArrayList<>(1); ++ forwardedFor.add(expectedRemoteAddr); ++ List forwardedProto = new ArrayList<>(1); ++ forwardedProto.add("https"); ++ reqHeaders.put("x-forwarded-for", forwardedFor); ++ reqHeaders.put("x-forwarded-proto", forwardedProto); ++ ++ getUrl("http://localhost:" + tomcat.getConnector().getLocalPort() + ++ "/test", null, reqHeaders, resHeaders); ++ String setCookie = resHeaders.get("Set-Cookie").get(0); ++ Assert.assertTrue(setCookie.contains("Secure")); ++ Assert.assertTrue(bug66471Servlet.isSecure.booleanValue()); ++ } ++ public static class Bug66471Servlet extends HttpServlet { ++ private static final long serialVersionUID = 1L; ++ public Boolean isSecure; ++ @Override ++ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ++ req.getSession(); ++ isSecure = (Boolean) req.getAttribute(Globals.REMOTE_IP_FILTER_SECURE); ++ } + } + } +diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml +index a97e15d..6a95e37 100644 +--- a/webapps/docs/changelog.xml ++++ b/webapps/docs/changelog.xml +@@ -60,6 +60,11 @@ + searching for nested groups when the JNDIRealm is configured with + roleNested set to true. (markt) + ++ ++ 66471: Fix JSessionId secure attribute missing When ++ RemoteIpFilter determines that this request was submitted ++ via a secure channel. (lihan) ++ + + Add connection pooling to JNDI realm. (remm) + +-- +2.36.1 + diff --git a/tomcat.spec b/tomcat.spec index a265276..c6d66b9 100644 --- a/tomcat.spec +++ b/tomcat.spec @@ -13,7 +13,7 @@ Name: tomcat Epoch: 1 Version: %{major_version}.%{minor_version}.%{micro_version} -Release: 27 +Release: 28 Summary: Implementation of the Java Servlet, JavaServer Pages, Java Expression Language and Java WebSocket technologies License: ASL 2.0 URL: http://tomcat.apache.org/ @@ -102,6 +102,7 @@ Patch6057: CVE-2021-41079.patch Patch6058: CVE-2021-42340.patch Patch6069: CVE-2022-23181.patch Patch6070: CVE-2022-42252.patch +Patch6071: CVE-2023-28708.patch BuildRequires: ecj >= 1:4.6.1 findutils apache-commons-collections apache-commons-daemon BuildRequires: apache-commons-dbcp apache-commons-pool tomcat-taglibs-standard ant @@ -503,6 +504,9 @@ fi %{_javadocdir}/%{name} %changelog +* Tue Apr 11 2023 mayp - 1:9.0.10-28 +- Fix CVE-2023-28708 + * Sun Jan 29 2023 yaoxin - 1:9.0.10-27 - Fix CVE-2022-42252 -- Gitee From bc7cebc7439d28f9597e8438876f5de830a95c44 Mon Sep 17 00:00:00 2001 From: mayp Date: Wed, 12 Apr 2023 14:31:51 +0800 Subject: [PATCH 2/6] fix CVE-2023-28708 --- CVE-2023-28708.patch | 235 ------------------------------------------- tomcat.spec | 6 +- 2 files changed, 1 insertion(+), 240 deletions(-) delete mode 100644 CVE-2023-28708.patch diff --git a/CVE-2023-28708.patch b/CVE-2023-28708.patch deleted file mode 100644 index 3d745e8..0000000 --- a/CVE-2023-28708.patch +++ /dev/null @@ -1,235 +0,0 @@ -From ca62c90b9e02a9931a2ce5acc61806858591d8b1 Mon Sep 17 00:00:00 2001 -From: mayp -Date: Tue, 11 Apr 2023 15:52:50 +0800 -Subject: [PATCH] Please enter the commit message for your changes. Lines - starting with '' will be ignored, and an empty message aborts the commit. - - On branch master - Changes to be committed: - modified: java/org/apache/catalina/Globals.java - modified: java/org/apache/catalina/connector/Request.java - modified: java/org/apache/catalina/filters/RemoteIpFilter.java - modified: test/org/apache/catalina/filters/TestRemoteIpFilter.java - modified: webapps/docs/changelog.xml ---- - java/org/apache/catalina/Globals.java | 7 ++ - .../apache/catalina/connector/Request.java | 14 +++ - .../catalina/filters/RemoteIpFilter.java | 7 +- - .../catalina/filters/TestRemoteIpFilter.java | 96 ++++++++++++++----- - webapps/docs/changelog.xml | 5 + - 5 files changed, 100 insertions(+), 29 deletions(-) - -diff --git a/java/org/apache/catalina/Globals.java b/java/org/apache/catalina/Globals.java -index 994902b..5b4cad6 100644 ---- a/java/org/apache/catalina/Globals.java -+++ b/java/org/apache/catalina/Globals.java -@@ -144,6 +144,13 @@ public final class Globals { - org.apache.coyote.Constants.SENDFILE_SUPPORTED_ATTR; - - -+ /** -+ * The request attribute that is set to the value of {@code Boolean.TRUE} -+ * if {@link org.apache.catalina.filters.RemoteIpFilter} determines -+ * that this request was submitted via a secure channel. -+ */ -+ public static final String REMOTE_IP_FILTER_SECURE = "org.apache.catalina.filters.RemoteIpFilter.secure"; -+ - /** - * The request attribute that can be used by a servlet to pass - * to the connector the name of the file that is to be served -diff --git a/java/org/apache/catalina/connector/Request.java b/java/org/apache/catalina/connector/Request.java -index c4cc26a..dd4c881 100644 ---- a/java/org/apache/catalina/connector/Request.java -+++ b/java/org/apache/catalina/connector/Request.java -@@ -3487,6 +3487,20 @@ public class Request implements HttpServletRequest { - // NO-OP - } - }); -+ specialAttributes.put(Globals.REMOTE_IP_FILTER_SECURE, -+ new SpecialAttributeAdapter() { -+ @Override -+ public Object get(Request request, String name) { -+ return Boolean.valueOf(request.isSecure()); -+ } -+ -+ @Override -+ public void set(Request request, String name, Object value) { -+ if (value instanceof Boolean) { -+ request.setSecure(((Boolean) value).booleanValue()); -+ } -+ } -+ }); - - for (SimpleDateFormat sdf : formatsTemplate) { - sdf.setTimeZone(GMT_ZONE); -diff --git a/java/org/apache/catalina/filters/RemoteIpFilter.java b/java/org/apache/catalina/filters/RemoteIpFilter.java -index b9f6655..e978cfb 100644 ---- a/java/org/apache/catalina/filters/RemoteIpFilter.java -+++ b/java/org/apache/catalina/filters/RemoteIpFilter.java -@@ -577,11 +577,6 @@ public class RemoteIpFilter extends GenericFilter { - return serverPort; - } - -- @Override -- public boolean isSecure() { -- return secure; -- } -- - public void removeHeader(String name) { - Map.Entry> header = getHeaderEntry(name); - if (header != null) { -@@ -617,7 +612,7 @@ public class RemoteIpFilter extends GenericFilter { - } - - public void setSecure(boolean secure) { -- this.secure = secure; -+ super.getRequest().setAttribute(Globals.REMOTE_IP_FILTER_SECURE, Boolean.valueOf(secure)); - } - - public void setServerPort(int serverPort) { -diff --git a/test/org/apache/catalina/filters/TestRemoteIpFilter.java b/test/org/apache/catalina/filters/TestRemoteIpFilter.java -index f7f2093..109fdd2 100644 ---- a/test/org/apache/catalina/filters/TestRemoteIpFilter.java -+++ b/test/org/apache/catalina/filters/TestRemoteIpFilter.java -@@ -81,15 +81,21 @@ public class TestRemoteIpFilter extends TomcatBaseTest { - - private static final long serialVersionUID = 1L; - -- private transient HttpServletRequest request; -- -- public HttpServletRequest getRequest() { -- return request; -- } -+ public String remoteAddr; -+ public String remoteHost; -+ public String scheme; -+ public String serverName; -+ public int serverPort; -+ public boolean isSecure; - - @Override - public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { -- this.request = request; -+ this.isSecure = request.isSecure(); -+ this.remoteAddr = request.getRemoteAddr(); -+ this.remoteHost = request.getRemoteHost(); -+ this.scheme = request.getScheme(); -+ this.serverName = request.getServerName(); -+ this.serverPort = request.getServerPort(); - PrintWriter writer = response.getWriter(); - - writer.println("request.remoteAddr=" + request.getRemoteAddr()); -@@ -127,16 +133,6 @@ public class TestRemoteIpFilter extends TomcatBaseTest { - getCoyoteRequest().scheme().setString(scheme); - } - -- @Override -- public void setAttribute(String name, Object value) { -- getCoyoteRequest().getAttributes().put(name, value); -- } -- -- @Override -- public Object getAttribute(String name) { -- return getCoyoteRequest().getAttributes().get(name); -- } -- - @Override - public String getServerName() { - return "localhost"; -@@ -667,16 +663,70 @@ public class TestRemoteIpFilter extends TomcatBaseTest { - - // VALIDATE - Assert.assertEquals(HttpURLConnection.HTTP_OK, httpURLConnection.getResponseCode()); -- HttpServletRequest request = mockServlet.getRequest(); -- Assert.assertNotNull(request); - - // VALIDATE X-FORWARDED-FOR -- Assert.assertEquals(expectedRemoteAddr, request.getRemoteAddr()); -- Assert.assertEquals(expectedRemoteAddr, request.getRemoteHost()); -+ Assert.assertEquals(expectedRemoteAddr, mockServlet.remoteAddr); -+ Assert.assertEquals(expectedRemoteAddr, mockServlet.remoteHost); - - // VALIDATE X-FORWARDED-PROTO -- Assert.assertTrue(request.isSecure()); -- Assert.assertEquals("https", request.getScheme()); -- Assert.assertEquals(443, request.getServerPort()); -+ Assert.assertTrue(mockServlet.isSecure); -+ Assert.assertEquals("https", mockServlet.scheme); -+ Assert.assertEquals(443, mockServlet.serverPort); -+ } -+ -+ @Test -+ public void testJSessionIdSecureAttributeMissing() throws Exception { -+ -+ // mostly default configuration : enable "x-forwarded-proto" -+ Map remoteIpFilterParameter = new HashMap<>(); -+ remoteIpFilterParameter.put("protocolHeader", "x-forwarded-proto"); -+ -+ // SETUP -+ Tomcat tomcat = getTomcatInstance(); -+ Context root = tomcat.addContext("", TEMP_DIR); -+ -+ FilterDef filterDef = new FilterDef(); -+ filterDef.getParameterMap().putAll(remoteIpFilterParameter); -+ filterDef.setFilterClass(RemoteIpFilter.class.getName()); -+ filterDef.setFilterName(RemoteIpFilter.class.getName()); -+ -+ root.addFilterDef(filterDef); -+ -+ FilterMap filterMap = new FilterMap(); -+ filterMap.setFilterName(RemoteIpFilter.class.getName()); -+ filterMap.addURLPatternDecoded("*"); -+ root.addFilterMap(filterMap); -+ -+ Bug66471Servlet bug66471Servlet = new Bug66471Servlet(); -+ -+ Tomcat.addServlet(root, bug66471Servlet.getClass().getName(), bug66471Servlet); -+ root.addServletMappingDecoded("/test", bug66471Servlet.getClass().getName()); -+ -+ getTomcatInstance().start(); -+ -+ Map> resHeaders = new HashMap<>(); -+ Map> reqHeaders = new HashMap<>(); -+ String expectedRemoteAddr = "my-remote-addr"; -+ List forwardedFor = new ArrayList<>(1); -+ forwardedFor.add(expectedRemoteAddr); -+ List forwardedProto = new ArrayList<>(1); -+ forwardedProto.add("https"); -+ reqHeaders.put("x-forwarded-for", forwardedFor); -+ reqHeaders.put("x-forwarded-proto", forwardedProto); -+ -+ getUrl("http://localhost:" + tomcat.getConnector().getLocalPort() + -+ "/test", null, reqHeaders, resHeaders); -+ String setCookie = resHeaders.get("Set-Cookie").get(0); -+ Assert.assertTrue(setCookie.contains("Secure")); -+ Assert.assertTrue(bug66471Servlet.isSecure.booleanValue()); -+ } -+ public static class Bug66471Servlet extends HttpServlet { -+ private static final long serialVersionUID = 1L; -+ public Boolean isSecure; -+ @Override -+ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { -+ req.getSession(); -+ isSecure = (Boolean) req.getAttribute(Globals.REMOTE_IP_FILTER_SECURE); -+ } - } - } -diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml -index a97e15d..6a95e37 100644 ---- a/webapps/docs/changelog.xml -+++ b/webapps/docs/changelog.xml -@@ -60,6 +60,11 @@ - searching for nested groups when the JNDIRealm is configured with - roleNested set to true. (markt) - -+ -+ 66471: Fix JSessionId secure attribute missing When -+ RemoteIpFilter determines that this request was submitted -+ via a secure channel. (lihan) -+ - - Add connection pooling to JNDI realm. (remm) - --- -2.36.1 - diff --git a/tomcat.spec b/tomcat.spec index c6d66b9..a265276 100644 --- a/tomcat.spec +++ b/tomcat.spec @@ -13,7 +13,7 @@ Name: tomcat Epoch: 1 Version: %{major_version}.%{minor_version}.%{micro_version} -Release: 28 +Release: 27 Summary: Implementation of the Java Servlet, JavaServer Pages, Java Expression Language and Java WebSocket technologies License: ASL 2.0 URL: http://tomcat.apache.org/ @@ -102,7 +102,6 @@ Patch6057: CVE-2021-41079.patch Patch6058: CVE-2021-42340.patch Patch6069: CVE-2022-23181.patch Patch6070: CVE-2022-42252.patch -Patch6071: CVE-2023-28708.patch BuildRequires: ecj >= 1:4.6.1 findutils apache-commons-collections apache-commons-daemon BuildRequires: apache-commons-dbcp apache-commons-pool tomcat-taglibs-standard ant @@ -504,9 +503,6 @@ fi %{_javadocdir}/%{name} %changelog -* Tue Apr 11 2023 mayp - 1:9.0.10-28 -- Fix CVE-2023-28708 - * Sun Jan 29 2023 yaoxin - 1:9.0.10-27 - Fix CVE-2022-42252 -- Gitee From 659cef36afffbfde8751daa5e7873f033be73c14 Mon Sep 17 00:00:00 2001 From: mayp Date: Thu, 13 Apr 2023 01:03:34 +0000 Subject: [PATCH 3/6] update tomcat.spec. Signed-off-by: mayp --- tomcat.spec | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tomcat.spec b/tomcat.spec index a265276..d6ec443 100644 --- a/tomcat.spec +++ b/tomcat.spec @@ -13,7 +13,7 @@ Name: tomcat Epoch: 1 Version: %{major_version}.%{minor_version}.%{micro_version} -Release: 27 +Release: 28 Summary: Implementation of the Java Servlet, JavaServer Pages, Java Expression Language and Java WebSocket technologies License: ASL 2.0 URL: http://tomcat.apache.org/ @@ -102,6 +102,7 @@ Patch6057: CVE-2021-41079.patch Patch6058: CVE-2021-42340.patch Patch6069: CVE-2022-23181.patch Patch6070: CVE-2022-42252.patch +Patch6071: CVE-2023-28708.patch BuildRequires: ecj >= 1:4.6.1 findutils apache-commons-collections apache-commons-daemon BuildRequires: apache-commons-dbcp apache-commons-pool tomcat-taglibs-standard ant @@ -503,6 +504,9 @@ fi %{_javadocdir}/%{name} %changelog +* Thu Apr 13 2023 mayp - 1:9.0.10-28 +- Fix CVE-2023-28708 + * Sun Jan 29 2023 yaoxin - 1:9.0.10-27 - Fix CVE-2022-42252 -- Gitee From 179aede9004722d4a46c024fedf2f4f6ba218e8f Mon Sep 17 00:00:00 2001 From: mayp Date: Thu, 13 Apr 2023 14:20:03 +0800 Subject: [PATCH 4/6] fix CVE-2023-28708 --- CVE-2023-28708.patch | 235 +++++++++++++++++++++++++++++++++++++++++++ tomcat.spec | 2 +- 2 files changed, 236 insertions(+), 1 deletion(-) create mode 100644 CVE-2023-28708.patch diff --git a/CVE-2023-28708.patch b/CVE-2023-28708.patch new file mode 100644 index 0000000..3d745e8 --- /dev/null +++ b/CVE-2023-28708.patch @@ -0,0 +1,235 @@ +From ca62c90b9e02a9931a2ce5acc61806858591d8b1 Mon Sep 17 00:00:00 2001 +From: mayp +Date: Tue, 11 Apr 2023 15:52:50 +0800 +Subject: [PATCH] Please enter the commit message for your changes. Lines + starting with '' will be ignored, and an empty message aborts the commit. + + On branch master + Changes to be committed: + modified: java/org/apache/catalina/Globals.java + modified: java/org/apache/catalina/connector/Request.java + modified: java/org/apache/catalina/filters/RemoteIpFilter.java + modified: test/org/apache/catalina/filters/TestRemoteIpFilter.java + modified: webapps/docs/changelog.xml +--- + java/org/apache/catalina/Globals.java | 7 ++ + .../apache/catalina/connector/Request.java | 14 +++ + .../catalina/filters/RemoteIpFilter.java | 7 +- + .../catalina/filters/TestRemoteIpFilter.java | 96 ++++++++++++++----- + webapps/docs/changelog.xml | 5 + + 5 files changed, 100 insertions(+), 29 deletions(-) + +diff --git a/java/org/apache/catalina/Globals.java b/java/org/apache/catalina/Globals.java +index 994902b..5b4cad6 100644 +--- a/java/org/apache/catalina/Globals.java ++++ b/java/org/apache/catalina/Globals.java +@@ -144,6 +144,13 @@ public final class Globals { + org.apache.coyote.Constants.SENDFILE_SUPPORTED_ATTR; + + ++ /** ++ * The request attribute that is set to the value of {@code Boolean.TRUE} ++ * if {@link org.apache.catalina.filters.RemoteIpFilter} determines ++ * that this request was submitted via a secure channel. ++ */ ++ public static final String REMOTE_IP_FILTER_SECURE = "org.apache.catalina.filters.RemoteIpFilter.secure"; ++ + /** + * The request attribute that can be used by a servlet to pass + * to the connector the name of the file that is to be served +diff --git a/java/org/apache/catalina/connector/Request.java b/java/org/apache/catalina/connector/Request.java +index c4cc26a..dd4c881 100644 +--- a/java/org/apache/catalina/connector/Request.java ++++ b/java/org/apache/catalina/connector/Request.java +@@ -3487,6 +3487,20 @@ public class Request implements HttpServletRequest { + // NO-OP + } + }); ++ specialAttributes.put(Globals.REMOTE_IP_FILTER_SECURE, ++ new SpecialAttributeAdapter() { ++ @Override ++ public Object get(Request request, String name) { ++ return Boolean.valueOf(request.isSecure()); ++ } ++ ++ @Override ++ public void set(Request request, String name, Object value) { ++ if (value instanceof Boolean) { ++ request.setSecure(((Boolean) value).booleanValue()); ++ } ++ } ++ }); + + for (SimpleDateFormat sdf : formatsTemplate) { + sdf.setTimeZone(GMT_ZONE); +diff --git a/java/org/apache/catalina/filters/RemoteIpFilter.java b/java/org/apache/catalina/filters/RemoteIpFilter.java +index b9f6655..e978cfb 100644 +--- a/java/org/apache/catalina/filters/RemoteIpFilter.java ++++ b/java/org/apache/catalina/filters/RemoteIpFilter.java +@@ -577,11 +577,6 @@ public class RemoteIpFilter extends GenericFilter { + return serverPort; + } + +- @Override +- public boolean isSecure() { +- return secure; +- } +- + public void removeHeader(String name) { + Map.Entry> header = getHeaderEntry(name); + if (header != null) { +@@ -617,7 +612,7 @@ public class RemoteIpFilter extends GenericFilter { + } + + public void setSecure(boolean secure) { +- this.secure = secure; ++ super.getRequest().setAttribute(Globals.REMOTE_IP_FILTER_SECURE, Boolean.valueOf(secure)); + } + + public void setServerPort(int serverPort) { +diff --git a/test/org/apache/catalina/filters/TestRemoteIpFilter.java b/test/org/apache/catalina/filters/TestRemoteIpFilter.java +index f7f2093..109fdd2 100644 +--- a/test/org/apache/catalina/filters/TestRemoteIpFilter.java ++++ b/test/org/apache/catalina/filters/TestRemoteIpFilter.java +@@ -81,15 +81,21 @@ public class TestRemoteIpFilter extends TomcatBaseTest { + + private static final long serialVersionUID = 1L; + +- private transient HttpServletRequest request; +- +- public HttpServletRequest getRequest() { +- return request; +- } ++ public String remoteAddr; ++ public String remoteHost; ++ public String scheme; ++ public String serverName; ++ public int serverPort; ++ public boolean isSecure; + + @Override + public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { +- this.request = request; ++ this.isSecure = request.isSecure(); ++ this.remoteAddr = request.getRemoteAddr(); ++ this.remoteHost = request.getRemoteHost(); ++ this.scheme = request.getScheme(); ++ this.serverName = request.getServerName(); ++ this.serverPort = request.getServerPort(); + PrintWriter writer = response.getWriter(); + + writer.println("request.remoteAddr=" + request.getRemoteAddr()); +@@ -127,16 +133,6 @@ public class TestRemoteIpFilter extends TomcatBaseTest { + getCoyoteRequest().scheme().setString(scheme); + } + +- @Override +- public void setAttribute(String name, Object value) { +- getCoyoteRequest().getAttributes().put(name, value); +- } +- +- @Override +- public Object getAttribute(String name) { +- return getCoyoteRequest().getAttributes().get(name); +- } +- + @Override + public String getServerName() { + return "localhost"; +@@ -667,16 +663,70 @@ public class TestRemoteIpFilter extends TomcatBaseTest { + + // VALIDATE + Assert.assertEquals(HttpURLConnection.HTTP_OK, httpURLConnection.getResponseCode()); +- HttpServletRequest request = mockServlet.getRequest(); +- Assert.assertNotNull(request); + + // VALIDATE X-FORWARDED-FOR +- Assert.assertEquals(expectedRemoteAddr, request.getRemoteAddr()); +- Assert.assertEquals(expectedRemoteAddr, request.getRemoteHost()); ++ Assert.assertEquals(expectedRemoteAddr, mockServlet.remoteAddr); ++ Assert.assertEquals(expectedRemoteAddr, mockServlet.remoteHost); + + // VALIDATE X-FORWARDED-PROTO +- Assert.assertTrue(request.isSecure()); +- Assert.assertEquals("https", request.getScheme()); +- Assert.assertEquals(443, request.getServerPort()); ++ Assert.assertTrue(mockServlet.isSecure); ++ Assert.assertEquals("https", mockServlet.scheme); ++ Assert.assertEquals(443, mockServlet.serverPort); ++ } ++ ++ @Test ++ public void testJSessionIdSecureAttributeMissing() throws Exception { ++ ++ // mostly default configuration : enable "x-forwarded-proto" ++ Map remoteIpFilterParameter = new HashMap<>(); ++ remoteIpFilterParameter.put("protocolHeader", "x-forwarded-proto"); ++ ++ // SETUP ++ Tomcat tomcat = getTomcatInstance(); ++ Context root = tomcat.addContext("", TEMP_DIR); ++ ++ FilterDef filterDef = new FilterDef(); ++ filterDef.getParameterMap().putAll(remoteIpFilterParameter); ++ filterDef.setFilterClass(RemoteIpFilter.class.getName()); ++ filterDef.setFilterName(RemoteIpFilter.class.getName()); ++ ++ root.addFilterDef(filterDef); ++ ++ FilterMap filterMap = new FilterMap(); ++ filterMap.setFilterName(RemoteIpFilter.class.getName()); ++ filterMap.addURLPatternDecoded("*"); ++ root.addFilterMap(filterMap); ++ ++ Bug66471Servlet bug66471Servlet = new Bug66471Servlet(); ++ ++ Tomcat.addServlet(root, bug66471Servlet.getClass().getName(), bug66471Servlet); ++ root.addServletMappingDecoded("/test", bug66471Servlet.getClass().getName()); ++ ++ getTomcatInstance().start(); ++ ++ Map> resHeaders = new HashMap<>(); ++ Map> reqHeaders = new HashMap<>(); ++ String expectedRemoteAddr = "my-remote-addr"; ++ List forwardedFor = new ArrayList<>(1); ++ forwardedFor.add(expectedRemoteAddr); ++ List forwardedProto = new ArrayList<>(1); ++ forwardedProto.add("https"); ++ reqHeaders.put("x-forwarded-for", forwardedFor); ++ reqHeaders.put("x-forwarded-proto", forwardedProto); ++ ++ getUrl("http://localhost:" + tomcat.getConnector().getLocalPort() + ++ "/test", null, reqHeaders, resHeaders); ++ String setCookie = resHeaders.get("Set-Cookie").get(0); ++ Assert.assertTrue(setCookie.contains("Secure")); ++ Assert.assertTrue(bug66471Servlet.isSecure.booleanValue()); ++ } ++ public static class Bug66471Servlet extends HttpServlet { ++ private static final long serialVersionUID = 1L; ++ public Boolean isSecure; ++ @Override ++ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ++ req.getSession(); ++ isSecure = (Boolean) req.getAttribute(Globals.REMOTE_IP_FILTER_SECURE); ++ } + } + } +diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml +index a97e15d..6a95e37 100644 +--- a/webapps/docs/changelog.xml ++++ b/webapps/docs/changelog.xml +@@ -60,6 +60,11 @@ + searching for nested groups when the JNDIRealm is configured with + roleNested set to true. (markt) + ++ ++ 66471: Fix JSessionId secure attribute missing When ++ RemoteIpFilter determines that this request was submitted ++ via a secure channel. (lihan) ++ + + Add connection pooling to JNDI realm. (remm) + +-- +2.36.1 + diff --git a/tomcat.spec b/tomcat.spec index d6ec443..c6d66b9 100644 --- a/tomcat.spec +++ b/tomcat.spec @@ -504,7 +504,7 @@ fi %{_javadocdir}/%{name} %changelog -* Thu Apr 13 2023 mayp - 1:9.0.10-28 +* Tue Apr 11 2023 mayp - 1:9.0.10-28 - Fix CVE-2023-28708 * Sun Jan 29 2023 yaoxin - 1:9.0.10-27 -- Gitee From bc4169caacb92bfd38965270c7b5086dcbe0b0ee Mon Sep 17 00:00:00 2001 From: mayp Date: Thu, 13 Apr 2023 14:47:01 +0800 Subject: [PATCH 5/6] fix CVE-2023-28708 --- CVE-2023-28708.patch | 235 ------------------------------------------- tomcat.spec | 6 +- 2 files changed, 1 insertion(+), 240 deletions(-) delete mode 100644 CVE-2023-28708.patch diff --git a/CVE-2023-28708.patch b/CVE-2023-28708.patch deleted file mode 100644 index 3d745e8..0000000 --- a/CVE-2023-28708.patch +++ /dev/null @@ -1,235 +0,0 @@ -From ca62c90b9e02a9931a2ce5acc61806858591d8b1 Mon Sep 17 00:00:00 2001 -From: mayp -Date: Tue, 11 Apr 2023 15:52:50 +0800 -Subject: [PATCH] Please enter the commit message for your changes. Lines - starting with '' will be ignored, and an empty message aborts the commit. - - On branch master - Changes to be committed: - modified: java/org/apache/catalina/Globals.java - modified: java/org/apache/catalina/connector/Request.java - modified: java/org/apache/catalina/filters/RemoteIpFilter.java - modified: test/org/apache/catalina/filters/TestRemoteIpFilter.java - modified: webapps/docs/changelog.xml ---- - java/org/apache/catalina/Globals.java | 7 ++ - .../apache/catalina/connector/Request.java | 14 +++ - .../catalina/filters/RemoteIpFilter.java | 7 +- - .../catalina/filters/TestRemoteIpFilter.java | 96 ++++++++++++++----- - webapps/docs/changelog.xml | 5 + - 5 files changed, 100 insertions(+), 29 deletions(-) - -diff --git a/java/org/apache/catalina/Globals.java b/java/org/apache/catalina/Globals.java -index 994902b..5b4cad6 100644 ---- a/java/org/apache/catalina/Globals.java -+++ b/java/org/apache/catalina/Globals.java -@@ -144,6 +144,13 @@ public final class Globals { - org.apache.coyote.Constants.SENDFILE_SUPPORTED_ATTR; - - -+ /** -+ * The request attribute that is set to the value of {@code Boolean.TRUE} -+ * if {@link org.apache.catalina.filters.RemoteIpFilter} determines -+ * that this request was submitted via a secure channel. -+ */ -+ public static final String REMOTE_IP_FILTER_SECURE = "org.apache.catalina.filters.RemoteIpFilter.secure"; -+ - /** - * The request attribute that can be used by a servlet to pass - * to the connector the name of the file that is to be served -diff --git a/java/org/apache/catalina/connector/Request.java b/java/org/apache/catalina/connector/Request.java -index c4cc26a..dd4c881 100644 ---- a/java/org/apache/catalina/connector/Request.java -+++ b/java/org/apache/catalina/connector/Request.java -@@ -3487,6 +3487,20 @@ public class Request implements HttpServletRequest { - // NO-OP - } - }); -+ specialAttributes.put(Globals.REMOTE_IP_FILTER_SECURE, -+ new SpecialAttributeAdapter() { -+ @Override -+ public Object get(Request request, String name) { -+ return Boolean.valueOf(request.isSecure()); -+ } -+ -+ @Override -+ public void set(Request request, String name, Object value) { -+ if (value instanceof Boolean) { -+ request.setSecure(((Boolean) value).booleanValue()); -+ } -+ } -+ }); - - for (SimpleDateFormat sdf : formatsTemplate) { - sdf.setTimeZone(GMT_ZONE); -diff --git a/java/org/apache/catalina/filters/RemoteIpFilter.java b/java/org/apache/catalina/filters/RemoteIpFilter.java -index b9f6655..e978cfb 100644 ---- a/java/org/apache/catalina/filters/RemoteIpFilter.java -+++ b/java/org/apache/catalina/filters/RemoteIpFilter.java -@@ -577,11 +577,6 @@ public class RemoteIpFilter extends GenericFilter { - return serverPort; - } - -- @Override -- public boolean isSecure() { -- return secure; -- } -- - public void removeHeader(String name) { - Map.Entry> header = getHeaderEntry(name); - if (header != null) { -@@ -617,7 +612,7 @@ public class RemoteIpFilter extends GenericFilter { - } - - public void setSecure(boolean secure) { -- this.secure = secure; -+ super.getRequest().setAttribute(Globals.REMOTE_IP_FILTER_SECURE, Boolean.valueOf(secure)); - } - - public void setServerPort(int serverPort) { -diff --git a/test/org/apache/catalina/filters/TestRemoteIpFilter.java b/test/org/apache/catalina/filters/TestRemoteIpFilter.java -index f7f2093..109fdd2 100644 ---- a/test/org/apache/catalina/filters/TestRemoteIpFilter.java -+++ b/test/org/apache/catalina/filters/TestRemoteIpFilter.java -@@ -81,15 +81,21 @@ public class TestRemoteIpFilter extends TomcatBaseTest { - - private static final long serialVersionUID = 1L; - -- private transient HttpServletRequest request; -- -- public HttpServletRequest getRequest() { -- return request; -- } -+ public String remoteAddr; -+ public String remoteHost; -+ public String scheme; -+ public String serverName; -+ public int serverPort; -+ public boolean isSecure; - - @Override - public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { -- this.request = request; -+ this.isSecure = request.isSecure(); -+ this.remoteAddr = request.getRemoteAddr(); -+ this.remoteHost = request.getRemoteHost(); -+ this.scheme = request.getScheme(); -+ this.serverName = request.getServerName(); -+ this.serverPort = request.getServerPort(); - PrintWriter writer = response.getWriter(); - - writer.println("request.remoteAddr=" + request.getRemoteAddr()); -@@ -127,16 +133,6 @@ public class TestRemoteIpFilter extends TomcatBaseTest { - getCoyoteRequest().scheme().setString(scheme); - } - -- @Override -- public void setAttribute(String name, Object value) { -- getCoyoteRequest().getAttributes().put(name, value); -- } -- -- @Override -- public Object getAttribute(String name) { -- return getCoyoteRequest().getAttributes().get(name); -- } -- - @Override - public String getServerName() { - return "localhost"; -@@ -667,16 +663,70 @@ public class TestRemoteIpFilter extends TomcatBaseTest { - - // VALIDATE - Assert.assertEquals(HttpURLConnection.HTTP_OK, httpURLConnection.getResponseCode()); -- HttpServletRequest request = mockServlet.getRequest(); -- Assert.assertNotNull(request); - - // VALIDATE X-FORWARDED-FOR -- Assert.assertEquals(expectedRemoteAddr, request.getRemoteAddr()); -- Assert.assertEquals(expectedRemoteAddr, request.getRemoteHost()); -+ Assert.assertEquals(expectedRemoteAddr, mockServlet.remoteAddr); -+ Assert.assertEquals(expectedRemoteAddr, mockServlet.remoteHost); - - // VALIDATE X-FORWARDED-PROTO -- Assert.assertTrue(request.isSecure()); -- Assert.assertEquals("https", request.getScheme()); -- Assert.assertEquals(443, request.getServerPort()); -+ Assert.assertTrue(mockServlet.isSecure); -+ Assert.assertEquals("https", mockServlet.scheme); -+ Assert.assertEquals(443, mockServlet.serverPort); -+ } -+ -+ @Test -+ public void testJSessionIdSecureAttributeMissing() throws Exception { -+ -+ // mostly default configuration : enable "x-forwarded-proto" -+ Map remoteIpFilterParameter = new HashMap<>(); -+ remoteIpFilterParameter.put("protocolHeader", "x-forwarded-proto"); -+ -+ // SETUP -+ Tomcat tomcat = getTomcatInstance(); -+ Context root = tomcat.addContext("", TEMP_DIR); -+ -+ FilterDef filterDef = new FilterDef(); -+ filterDef.getParameterMap().putAll(remoteIpFilterParameter); -+ filterDef.setFilterClass(RemoteIpFilter.class.getName()); -+ filterDef.setFilterName(RemoteIpFilter.class.getName()); -+ -+ root.addFilterDef(filterDef); -+ -+ FilterMap filterMap = new FilterMap(); -+ filterMap.setFilterName(RemoteIpFilter.class.getName()); -+ filterMap.addURLPatternDecoded("*"); -+ root.addFilterMap(filterMap); -+ -+ Bug66471Servlet bug66471Servlet = new Bug66471Servlet(); -+ -+ Tomcat.addServlet(root, bug66471Servlet.getClass().getName(), bug66471Servlet); -+ root.addServletMappingDecoded("/test", bug66471Servlet.getClass().getName()); -+ -+ getTomcatInstance().start(); -+ -+ Map> resHeaders = new HashMap<>(); -+ Map> reqHeaders = new HashMap<>(); -+ String expectedRemoteAddr = "my-remote-addr"; -+ List forwardedFor = new ArrayList<>(1); -+ forwardedFor.add(expectedRemoteAddr); -+ List forwardedProto = new ArrayList<>(1); -+ forwardedProto.add("https"); -+ reqHeaders.put("x-forwarded-for", forwardedFor); -+ reqHeaders.put("x-forwarded-proto", forwardedProto); -+ -+ getUrl("http://localhost:" + tomcat.getConnector().getLocalPort() + -+ "/test", null, reqHeaders, resHeaders); -+ String setCookie = resHeaders.get("Set-Cookie").get(0); -+ Assert.assertTrue(setCookie.contains("Secure")); -+ Assert.assertTrue(bug66471Servlet.isSecure.booleanValue()); -+ } -+ public static class Bug66471Servlet extends HttpServlet { -+ private static final long serialVersionUID = 1L; -+ public Boolean isSecure; -+ @Override -+ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { -+ req.getSession(); -+ isSecure = (Boolean) req.getAttribute(Globals.REMOTE_IP_FILTER_SECURE); -+ } - } - } -diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml -index a97e15d..6a95e37 100644 ---- a/webapps/docs/changelog.xml -+++ b/webapps/docs/changelog.xml -@@ -60,6 +60,11 @@ - searching for nested groups when the JNDIRealm is configured with - roleNested set to true. (markt) - -+ -+ 66471: Fix JSessionId secure attribute missing When -+ RemoteIpFilter determines that this request was submitted -+ via a secure channel. (lihan) -+ - - Add connection pooling to JNDI realm. (remm) - --- -2.36.1 - diff --git a/tomcat.spec b/tomcat.spec index c6d66b9..a265276 100644 --- a/tomcat.spec +++ b/tomcat.spec @@ -13,7 +13,7 @@ Name: tomcat Epoch: 1 Version: %{major_version}.%{minor_version}.%{micro_version} -Release: 28 +Release: 27 Summary: Implementation of the Java Servlet, JavaServer Pages, Java Expression Language and Java WebSocket technologies License: ASL 2.0 URL: http://tomcat.apache.org/ @@ -102,7 +102,6 @@ Patch6057: CVE-2021-41079.patch Patch6058: CVE-2021-42340.patch Patch6069: CVE-2022-23181.patch Patch6070: CVE-2022-42252.patch -Patch6071: CVE-2023-28708.patch BuildRequires: ecj >= 1:4.6.1 findutils apache-commons-collections apache-commons-daemon BuildRequires: apache-commons-dbcp apache-commons-pool tomcat-taglibs-standard ant @@ -504,9 +503,6 @@ fi %{_javadocdir}/%{name} %changelog -* Tue Apr 11 2023 mayp - 1:9.0.10-28 -- Fix CVE-2023-28708 - * Sun Jan 29 2023 yaoxin - 1:9.0.10-27 - Fix CVE-2022-42252 -- Gitee From 435a07111fb1af46bea96df4b3bcab6f9e206130 Mon Sep 17 00:00:00 2001 From: mayp Date: Thu, 13 Apr 2023 07:15:43 +0000 Subject: [PATCH 6/6] update tomcat.spec. Signed-off-by: mayp --- tomcat.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tomcat.spec b/tomcat.spec index a265276..7be2778 100644 --- a/tomcat.spec +++ b/tomcat.spec @@ -13,7 +13,7 @@ Name: tomcat Epoch: 1 Version: %{major_version}.%{minor_version}.%{micro_version} -Release: 27 +Release: 28 Summary: Implementation of the Java Servlet, JavaServer Pages, Java Expression Language and Java WebSocket technologies License: ASL 2.0 URL: http://tomcat.apache.org/ @@ -503,6 +503,9 @@ fi %{_javadocdir}/%{name} %changelog +* Thu Apr 13 2023 mayp - 1:9.0.10-28 +- commit + * Sun Jan 29 2023 yaoxin - 1:9.0.10-27 - Fix CVE-2022-42252 -- Gitee