From 5afe9decbaf20d9bea902804dcad789ecf8ef2c2 Mon Sep 17 00:00:00 2001 From: xu_lei_123 Date: Mon, 26 Dec 2022 11:08:06 +0800 Subject: [PATCH] fix CVE-2022-2047 --- CVE-2022-2047.patch | 302 ++++++++++++++++++++++++++++++++++++++++++++ jetty.spec | 6 +- 2 files changed, 307 insertions(+), 1 deletion(-) create mode 100644 CVE-2022-2047.patch diff --git a/CVE-2022-2047.patch b/CVE-2022-2047.patch new file mode 100644 index 0000000..2e73f7a --- /dev/null +++ b/CVE-2022-2047.patch @@ -0,0 +1,302 @@ +diff -uprN jetty.project-jetty-9.4.16.v20190411_back/jetty-client/src/main/java/org/eclipse/jetty/client/HttpRequest.java jetty.project-jetty-9.4.16.v20190411/jetty-client/src/main/java/org/eclipse/jetty/client/HttpRequest.java +--- jetty.project-jetty-9.4.16.v20190411_back/jetty-client/src/main/java/org/eclipse/jetty/client/HttpRequest.java 2022-12-13 20:04:18.237000000 +0800 ++++ jetty.project-jetty-9.4.16.v20190411/jetty-client/src/main/java/org/eclipse/jetty/client/HttpRequest.java 2022-12-13 15:49:40.806121800 +0800 +@@ -177,6 +177,8 @@ public class HttpRequest implements Requ + String rawPath = uri.getRawPath(); + if (rawPath == null) + rawPath = ""; ++ if (!rawPath.startsWith("/")) ++ rawPath = "/" + rawPath; + this.path = rawPath; + String query = uri.getRawQuery(); + if (query != null) +@@ -855,14 +857,14 @@ public class HttpRequest implements Requ + return result; + } + +- private URI newURI(String uri) ++ private URI newURI(String path) + { + try + { + // Handle specially the "OPTIONS *" case, since it is possible to create a URI from "*" (!). +- if ("*".equals(uri)) ++ if ("*".equals(path)) + return null; +- URI result = new URI(uri); ++ URI result = new URI(path); + return result.isOpaque() ? null : result; + } + catch (URISyntaxException x) +diff -uprN jetty.project-jetty-9.4.16.v20190411_back/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientURITest.java jetty.project-jetty-9.4.16.v20190411/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientURITest.java +--- jetty.project-jetty-9.4.16.v20190411_back/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientURITest.java 2022-12-13 20:04:18.241000000 +0800 ++++ jetty.project-jetty-9.4.16.v20190411/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientURITest.java 2022-12-13 15:49:33.335326400 +0800 +@@ -36,8 +36,10 @@ import java.net.SocketException; + import java.net.URLEncoder; + import java.nio.charset.StandardCharsets; + import java.util.Locale; ++import java.util.concurrent.CountDownLatch; + import java.util.concurrent.ExecutionException; + import java.util.concurrent.TimeUnit; ++import java.util.concurrent.atomic.AtomicReference; + + import javax.servlet.ServletException; + import javax.servlet.http.HttpServletRequest; +@@ -79,6 +81,49 @@ public class HttpClientURITest extends A + } + + @ParameterizedTest ++ @ArgumentsSource(ScenarioProvider.class) ++ public void testPathWithPathParameter(Scenario scenario) throws Exception ++ { ++ AtomicReference serverLatchRef = new AtomicReference<>(); ++ start(scenario, new EmptyServerHandler() ++ { ++ @Override ++ protected void service(String target, org.eclipse.jetty.server.Request jettyRequest, HttpServletRequest request, HttpServletResponse response) ++ { ++ if (jettyRequest.getHttpURI().hasAmbiguousEmptySegment()) ++ response.setStatus(400); ++ serverLatchRef.get().countDown(); ++ } ++ }); ++ ++ serverLatchRef.set(new CountDownLatch(1)); ++ ContentResponse response1 = client.newRequest("localhost", connector.getLocalPort()) ++ .scheme(scenario.getScheme()) ++ .path("/url;p=v") ++ .send(); ++ assertEquals(HttpStatus.OK_200, response1.getStatus()); ++ assertTrue(serverLatchRef.get().await(5, TimeUnit.SECONDS)); ++ ++ // Ambiguous empty segment. ++ serverLatchRef.set(new CountDownLatch(1)); ++ ContentResponse response2 = client.newRequest("localhost", connector.getLocalPort()) ++ .scheme(scenario.getScheme()) ++ .path(";p=v/url") ++ .send(); ++ assertEquals(HttpStatus.BAD_REQUEST_400, response2.getStatus()); ++ assertTrue(serverLatchRef.get().await(5, TimeUnit.SECONDS)); ++ ++ // Ambiguous empty segment. ++ serverLatchRef.set(new CountDownLatch(1)); ++ ContentResponse response3 = client.newRequest("localhost", connector.getLocalPort()) ++ .scheme(scenario.getScheme()) ++ .path(";@host.org/url") ++ .send(); ++ assertEquals(HttpStatus.BAD_REQUEST_400, response3.getStatus()); ++ assertTrue(serverLatchRef.get().await(5, TimeUnit.SECONDS)); ++ } ++ ++ @ParameterizedTest + @ArgumentsSource(ScenarioProvider.class) + public void testIDNHost(Scenario scenario) throws Exception + { +diff -uprN jetty.project-jetty-9.4.16.v20190411_back/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java jetty.project-jetty-9.4.16.v20190411/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java +--- jetty.project-jetty-9.4.16.v20190411_back/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java 2022-12-13 20:04:18.285000000 +0800 ++++ jetty.project-jetty-9.4.16.v20190411/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java 2022-12-13 21:48:14.310756581 +0800 +@@ -189,7 +189,7 @@ public class HttpURI + _uri=uri; + + if (HttpMethod.CONNECT.is(method)) +- _path=uri; ++ parse(State.HOST, uri, 0, uri.length()); + else + parse(uri.startsWith("/")?State.PATH:State.START,uri,0,uri.length()); + } +@@ -720,35 +720,55 @@ public class HttpURI + */ + public void setAuthority(String host, int port) + { ++ if (host != null && !isPathValidForAuthority(_path)) ++ throw new IllegalArgumentException("Relative path with authority"); + _host=host; + _port=port; + _uri=null; + } + ++ private boolean isPathValidForAuthority(String path) ++ { ++ if (path == null) ++ return true; ++ if (path.isEmpty() || "*".equals(path)) ++ return true; ++ return path.startsWith("/"); ++ } ++ + /* ------------------------------------------------------------ */ + /** + * @param path the path + */ + public void setPath(String path) + { ++ if (hasAuthority() && !isPathValidForAuthority(path)) ++ throw new IllegalArgumentException("Relative path with authority"); + _uri=null; + _path=path; + _decodedPath=null; + } + + /* ------------------------------------------------------------ */ +- public void setPathQuery(String path) ++ public void setPathQuery(String pathQuery) + { ++ if (hasAuthority() && !isPathValidForAuthority(pathQuery)) ++ throw new IllegalArgumentException("Relative path with authority"); + _uri=null; + _path=null; + _decodedPath=null; + _param=null; + _fragment=null; +- if (path!=null) +- parse(State.PATH,path,0,path.length()); ++ if (pathQuery!=null) ++ parse(State.PATH,pathQuery,0,pathQuery.length()); + } + + /* ------------------------------------------------------------ */ ++ private boolean hasAuthority() ++ { ++ return _host != null; ++ } ++ + public void setQuery(String query) + { + _query=query; +diff -uprN jetty.project-jetty-9.4.16.v20190411_back/jetty-http/src/test/java/org/eclipse/jetty/http/HttpURITest.java jetty.project-jetty-9.4.16.v20190411/jetty-http/src/test/java/org/eclipse/jetty/http/HttpURITest.java +--- jetty.project-jetty-9.4.16.v20190411_back/jetty-http/src/test/java/org/eclipse/jetty/http/HttpURITest.java 2022-12-13 20:04:18.288000000 +0800 ++++ jetty.project-jetty-9.4.16.v20190411/jetty-http/src/test/java/org/eclipse/jetty/http/HttpURITest.java 2022-12-13 15:49:24.364726300 +0800 +@@ -101,6 +101,32 @@ public class HttpURITest + } + + @Test ++ public void testCONNECT() ++ { ++ HttpURI uri = new HttpURI(); ++ ++ uri.parseRequestTarget("CONNECT", "host:80"); ++ assertThat(uri.getHost(), is("host")); ++ assertThat(uri.getPort(), is(80)); ++ assertThat(uri.getPath(), nullValue()); ++ ++ uri.parseRequestTarget("CONNECT", "host"); ++ assertThat(uri.getHost(), is("host")); ++ assertThat(uri.getPort(), is(-1)); ++ assertThat(uri.getPath(), nullValue()); ++ ++ uri.parseRequestTarget("CONNECT", "192.168.0.1:8080"); ++ assertThat(uri.getHost(), is("192.168.0.1")); ++ assertThat(uri.getPort(), is(8080)); ++ assertThat(uri.getPath(), nullValue()); ++ ++ uri.parseRequestTarget("CONNECT", "[::1]:8080"); ++ assertThat(uri.getHost(), is("[::1]")); ++ assertThat(uri.getPort(), is(8080)); ++ assertThat(uri.getPath(), nullValue()); ++ } ++ ++ @Test + public void testExtB() throws Exception + { + for (String value: new String[]{"a","abcdABCD","\u00C0","\u697C","\uD869\uDED5","\uD840\uDC08"} ) +@@ -222,4 +248,64 @@ public class HttpURITest + assertEquals(uri.getAuthority(), "example.com:8888"); + assertEquals(uri.getUser(), "user:password"); + } ++ ++ @Test ++ public void testRelativePathWithAuthority() ++ { ++ assertThrows(IllegalArgumentException.class, () -> ++ { ++ HttpURI httpURI = new HttpURI(); ++ httpURI.setAuthority("host", 0); ++ httpURI.setPath("path"); ++ }); ++ assertThrows(IllegalArgumentException.class, () -> ++ { ++ HttpURI httpURI = new HttpURI(); ++ httpURI.setAuthority("host", 8080); ++ httpURI.setPath(";p=v/url"); ++ }); ++ assertThrows(IllegalArgumentException.class, () -> ++ { ++ HttpURI httpURI = new HttpURI(); ++ httpURI.setAuthority("host", 0); ++ httpURI.setPath(";"); ++ }); ++ ++ assertThrows(IllegalArgumentException.class, () -> ++ { ++ HttpURI httpURI = new HttpURI(); ++ httpURI.setPath("path"); ++ httpURI.setAuthority("host", 0); ++ }); ++ assertThrows(IllegalArgumentException.class, () -> ++ { ++ HttpURI httpURI = new HttpURI(); ++ httpURI.setPath(";p=v/url"); ++ httpURI.setAuthority("host", 8080); ++ }); ++ assertThrows(IllegalArgumentException.class, () -> ++ { ++ HttpURI httpURI = new HttpURI(); ++ httpURI.setPath(";"); ++ httpURI.setAuthority("host", 0); ++ }); ++ ++ HttpURI uri = new HttpURI(); ++ uri.setPath("*"); ++ uri.setAuthority("host", 0); ++ assertEquals("//host*", uri.toString()); ++ uri = new HttpURI(); ++ uri.setAuthority("host", 0); ++ uri.setPath("*"); ++ assertEquals("//host*", uri.toString()); ++ ++ uri = new HttpURI(); ++ uri.setPath(""); ++ uri.setAuthority("host", 0); ++ assertEquals("//host", uri.toString()); ++ uri = new HttpURI(); ++ uri.setAuthority("host", 0); ++ uri.setPath(""); ++ assertEquals("//host", uri.toString()); ++ } + } +diff -uprN jetty.project-jetty-9.4.16.v20190411_back/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/ConnectHandler.java jetty.project-jetty-9.4.16.v20190411/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/ConnectHandler.java +--- jetty.project-jetty-9.4.16.v20190411_back/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/ConnectHandler.java 2022-12-13 20:04:18.361000000 +0800 ++++ jetty.project-jetty-9.4.16.v20190411/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/ConnectHandler.java 2022-12-13 15:48.14.684794100 +0800 +@@ -197,7 +197,7 @@ public class ConnectHandler extends Hand + { + if (HttpMethod.CONNECT.is(request.getMethod())) + { +- String serverAddress = request.getRequestURI(); ++ String serverAddress = baseRequest.getHttpURI().getAuthority(); + if (LOG.isDebugEnabled()) + LOG.debug("CONNECT request for {}", serverAddress); + +diff -uprN jetty.project-jetty-9.4.16.v20190411_back/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java jetty.project-jetty-9.4.16.v20190411/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java +--- jetty.project-jetty-9.4.16.v20190411_back/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java 2022-12-13 20:04:18.377000000 +0800 ++++ jetty.project-jetty-9.4.16.v20190411/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java 2022-12-13 15:48.14.151348100 +0800 +@@ -1778,9 +1778,18 @@ public class Request implements HttpServ + + setMethod(request.getMethod()); + HttpURI uri = request.getURI(); +- _originalURI = uri.isAbsolute()&&request.getHttpVersion()!=HttpVersion.HTTP_2?uri.toString():uri.getPathQuery(); ++ String encoded; ++ if (HttpMethod.CONNECT.is(request.getMethod())) ++ { ++ _originalURI = uri.getAuthority(); ++ encoded = "/"; ++ } ++ else ++ { ++ _originalURI = uri.isAbsolute() && request.getHttpVersion() != HttpVersion.HTTP_2 ? uri.toString() : uri.getPathQuery(); ++ encoded = uri.getPath(); ++ } + +- String encoded = uri.getPath(); + String path; + if (encoded==null) + { diff --git a/jetty.spec b/jetty.spec index b49c5eb..15a3886 100644 --- a/jetty.spec +++ b/jetty.spec @@ -12,7 +12,7 @@ %bcond_with jp_minimal Name: jetty Version: 9.4.16 -Release: 1 +Release: 2 Summary: Java Webserver and Servlet Container License: ASL 2.0 or EPL-1.0 or EPL-2.0 URL: http://www.eclipse.org/jetty/ @@ -26,6 +26,7 @@ Patch1: CVE-2020-27223.patch Patch2: CVE-2021-28165.patch Patch3: CVE-2021-28169.patch Patch4: CVE-2021-34428.patch +Patch5: CVE-2022-2047.patch BuildRequires: maven-local mvn(javax.servlet:javax.servlet-api) BuildRequires: mvn(org.apache.felix:maven-bundle-plugin) @@ -785,6 +786,9 @@ exit 0 %license LICENSE NOTICE.txt LICENSE-MIT %changelog +* Wed Dec 21 2022 xulei - 9.4.16-2 +- fix CVE-2022-2047 + * Tue Sep 13 2022 liangqifeng - 9.4.16-1 - update to 9.4.14 to Fix CVE-2019-10241 -- Gitee